请继续在笔记3的基础上开发。
导读:
本章内容学习:
- 登录表单(form)中的数据以GET/POST提交到服务器;
- Django验证用户名/密码的正确性;
- 验证成功后如何处理;
- 验证失败将错误提示返回客户端。
一、先写个登录界面
打开…/sign/templates/index.html文件
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django Demo</title>
</head>
<body>
<h1>发布会管理</h1>
<form>
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password" ><br>
<button id="btn" type="submit">登录</button>
</form>
</body>
</html>
启动D服务,访问:http://127.0.0.1:8000/index/
上图我们看到登录界面已经写好了,但它还不可用。
接下来我通GET与POST请求来实现登录功能。
二、GET与POST请求
2.1GET请求
(get传参方式:form method=“get”)
打开…/sign/templates/index.html文件
index.html
......
<form method="get">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password" ><br>
<button id="btn" type="submit">登录</button>
</form>
......
刷新登录页面,输入用户名/密码(admin/admin123),单击“登录”按钮
查看浏览器URL地址栏:
http://127.0.0.1:8000/index/?username=admin&password=admin123
GET方法会将用户提交的数据添加到URL地址中,路径后面跟问号“?”。username为HTML代码中<input>标签的name属性值(name=“username”),admin是我们在用户名输入框中填写的用户名。password=admin123的取值方式与用户名相同。多个参数之间“&”符号隔开。
2.2POST请求
同样是上面的代码,将form表单中的属性修改为method=“post”,刷新页面,输入用户名/密码(admin/admin123),单击“登录”按钮。弹出“CSRF verification failed. Request aborted.”
......
<form method="post">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password" ><br>
<button id="btn" type="submit">登录</button>
</form>
......
看到这个报错,不要着急,静下心来仔细阅读上面的帮助信息。
这个错误是说我们在使用Django的模板未正确使用CSRF(Cross-Site Request Forgery “跨站请求伪造”)令牌!Django针对CSRF的保护措施是在生成的每个表单中放置一个自动生成的令牌,通过这个令牌判断POST请求是否来自同一个网站。
之前的模板都是纯粹的HTML,这里首次用到Django的模板,使用“模板标签”(TemplateTag)添加CSRF令牌。在from表单中添加{% csrf_token %}。
<form method="post">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password" ><br>
<button id="btn" type="submit">登录</button>
{% csrf_token %}
</form>
然后,刷新页面,输入用户名/密码(admin/admin123),单击“登录”按钮。按F12调试工具查看POST请求,我们会看到除了“usrnname"和”password“参数外,还多了一个”csrfmiddlewaretoken“的参数。当页面向Django服务器发送一个POST请求时,服务器端要求客端加上”csrfmiddlewaretoken“字段,该字段的值为当前会话ID加上一个密钥的散列值。
如果想忽略掉该检查,那么可以在…/guest/settings.py文件中注释掉csrf。
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
三、处理登录请求
那么Django是如何接收请求的数据并加以处理的呢?可以通过form表单的action属性来指定提交的路径。
打开index.html文件,添加内容如下:
......
<form method="post" action="/login_action/">
......
当我们填写用户名/密码,单击”登录“按钮时,由http://127.0.0.1:8000/login_action/路径来提交登录请求。所以,打开…/guest/urls.py文件添加login_action的路由。
from sign import views #导入sign应用views文件
urlpatterns = [
......
url(r'login_action/$',views.login_action),
]
登录请求由views.py视图文件的login_action函数来处理,打开sign/views.py文件,创建login_action视图函数。
......
# 登录动作
def login_action(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if username == 'admin' and password == 'admin123':
return HttpResponse('登录成功!')
else:
return render(request,'index.html',{'error':'用户名密码错误!'})
分析:
1、首先,通过request.method得到客户端的请求方式,并判断其是否为POST方式的请求。
2、接着,通过request.POST来获取POST请求。通过.get()方法获取“username”和“password”所获取的用户名/密码(admin/admin123)。如果参数为空,则返回一个空的字符串。
3、最后,通过if语句判断username和passwoed的值是否为“admin/admin123”。如果是则通过HttpResponse类返回字符串“登录成功”。否则,将通过render返回index.html登录页面,并且顺带返回错误提示的字典{‘error’:‘用户名和密码错误!’}。
但是,登录页面并没有显示错误提示的位置,打开index.html页面修改如下:
<form method="post" action="/login_action/">
<input name="username" type="text" placeholder="username" ><br>
<input name="password" type="password" placeholder="password" ><br>
{{ error }}<br>
<button id="btn" type="submit">登录</button>
{% csrf_token %}
</form>
使用Django的模板语言,添加{{ error }}
,它对应render返回字典中的key,即‘error’在登录失败的页面中显示对应的value,即’用户名密码错误!‘。
好了,现在来体验下登录功能。
四、登录成功页
登录成功返回”登录成功!”字符串只是一种临时方案,只是为了方便验证登录的处理逻辑,现在验证没有问题之后,需要通过HTML页面来替换。
首先,创建…/templates/event_manage.html页面。(发布会管理页面)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>发布会管理系统</title>
</head>
<body>
<h1>登录成功!</h1>
</body>
</html>
打开…/sign/views.py文件,修改内容:
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
......
# 登录动作
def login_action(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
if username == 'admin' and password == 'admin123':
return HttpResponseRedirect('/event_manage/')
else:
return render(request,'index.html',{'error':'用户名密码错误!'})
# 发布会管理
def event_manage(request):
return render(request,"event_manage.html")
此处用到一个新类HttpResponseRedirect,它可以对路径进行重定向,从而将登录成功之后的请求指向/event_manage/目录,即:http://127.0.0.1:8000/event_manage/
创建event_manage函数,用于返回发布会管理页面event_manage.html。
最后,我们要记的在…/guest.urls.py 文件中添加event_manage/的路由。
from sign import views #导入sign应用views文件
urlpatterns = [
......
url(r'event_manage/$',views.event_manage),
]
再来登录一下,试试修改后的功能吧!