Django初学者索引4 - 新建一个登陆窗口
开始的话
新上线的后台编辑末班很不错,赞一个。
事实证明,写笔记比看书重要,隔了差不多一个月,书又得重头看,看笔记一下把当时的状态找回来了,因此继续。
今天的目标-实现web登录功能
- 用之前默认的index.html页面来做实验
- 建立一个最简单的登陆界面
- 通过get post功能验证是否可以登陆
第一步建立简单的HTML登陆页面
直接上代码:
// 登陆页面的基础html代码
<html>
<head>
<title>我的登陆测试页面</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>
这里我们有了一个简单的样式,但是没有实现相关功能,下面逐步完善。
增加get请求
将form标签改为如下代码即可
这样我们通过用户名:admin,密码:admin123,点击登陆窗口,url会变成下面截图的样子
相当于将用户名,密码传递到了后台。
增加post请求
将form标签改为如下代码即可
这时会出现403的警告,原因是出发了django的安全规范,即可能触发跨站请求伪造漏洞,解决方法很简单,在form的最后一行增加{% csrf_token %}代码即可,如下图:
这时再刷新并重新提交表单,即成功了,但URL和页面没有任何变化,实际上是生成了一个安全的token,截图如下:
大家可以看到除了传送到服务端,用户名和密码外,还传送了这个安全的token,同时,不改变url的内容,让破解者无法了解请求参数,这也是post请求比get请求安全的原因。
当然如果想忽略掉这个检查也可以,需要在setting.py 进行注释即可,如下图:
不过出于安全角度,不建议注释掉这个安全功能。
简单的看一下效果
我们请求发过去了,怎么知道后代的响应方法呢,我们需要在页面上再做一些改动,增加下面的代码:
{{error}}<br>
添加代码的位置如下:
然后我们需要写一些代码,判断前端页面传过来的参数,这里我们又需要改一下页面,调用一个行为login_action,修改方法为将form改为下面的样子,这时就调用了后台的一个请求。
<form method="post" action="/logon_action/">
因为是在默认页面上发生的请求,默认页面属于index的解析环境,因此简要考虑,直接在主路由文件上做解析:
from django.urls import path, include, re_path
from index.views import index, login_action
re_path('login_action/*', login_action),
代码位置如下图
为什么用re_path,我们一会再说,这几行的意思就是当前台请求login_action这个开头的url时候,通过login_aciton这个函数来解析,这个函数放在了index.views的文件里,于是我们打开index/views/py,添加如下代码:
def login_action(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
print(username)
print(password)
if username == 'admin' and password == 'admin123':
return render(request,'index.html', {'error':'login success!'})
else:
return render(request,'index.html', {'error':'bad username or password!'})
这段话的意思就是,如果判断前端提交代码中的username和password是否是指定的内容,如果是返回login success的字样,如果不是,返回bad username or password!
这中间的print可以让前端传回来的 username 和password 在后台打印,以监测是否解析正确,正式代码中应写入日志;
意外分析
如果我们多按几次登录会发现url会变得越来越长,如下图:
用户的每次点击都会让url变得更长一些,这就是我们前面提到的 re_path的功能了,re_path是通过正则表达式的方式解析URL,如果用正常的path,后面新增了内容,页面就无法正常显示了,现在我们把login_action开头的url都返回这个信息就好了。
如果修改url让大家认为链接没有改变呢,肯定是有办法的,这个我们在以后再讲。
实现页面跳转
正常的页面在登录之后不是显示登录正确而是跳转到新的页面,这时我们只需要修改 login_action函数的返回信息即可,
需要修改的代码如下:
from django.http import HttpResponse, HttpResponseRedirect
第一行为调用页面重定向函数
第二行为将登录成功的页面,重定向到某个页面;
不要忘记将新的页面加入到url路由中,代码如下
添加路由
添加解析:
在templates里新增login.html文件,内容为:
总结:
今天实现了简单的登录功能,实际上是实现了前后端的交互、跳转、返回信息等几个关键节点,从一定角度上说,这就是实现了前后端的拉通,但这还很初级,还有很多高级的功能需要逐步学习。
遗留问题:
1、密码在数据库中查询和调取;
2、url怎么设置不变;
3、get方式提交该怎么处理;
…
增强功能,实现cookie和session
cookie和session是两个保持用户登录状态的方法,在django中可以轻松实现,
实现cookie
response.set_cookie('user', username, 3600)
username = request.COOKIES.get('user','')
前两行一个是写入cookie,一个是读取cookie,实现了cookie的功能,第三行是
在login.html上增加获取cookie的代码,如下
<div style="float:right">
<a>hi {{user}}, welcome!!</a>
</div>
实现的效果如下(cookie调用成功):
实现session
还是修改刚才的两个位置,一个是解析,一个是读取
request.session['user'] = username
username = request.session.get('user', '')
代码截图如下:
重新访问页面,报错!
因为session是将用户信息存在服务器,那么服务器到指定的位置找数据没有找到,解决的方法是建立数据库,关于django的数据库,我们后面详细说,这里只是先写几个命令。
python3 manage.py migrate
这时候再登录一下,就显示成功了,这样我们就把登录系统用到的知识点一次性模拟出来了。
用django的用户管理功能登录
开启后台用户管理功能
这个很简单,大家用过django的都应该知道
python3 manage.py createsuperuser
过程中,需要我们输入用户名,密码,然后就可以了
打开登录地址http://127.0.0.1:8000/admin/ ,然后大家就看到了django引以为豪的后台管理界面了,这里我将原来的认证程序转成django支持的数据库认证模式。
修改views.py 内的login_action解析
主要修改了以下内容:
from django.contrib import auth
user= auth.authenticate(username=username, password = password)
if user is not None:
auth.login(request, user)
auth.authenticate(),验证用户名密码后,正确返回user name,错误返回None,所以通过None,来判断是否登录成功,具体代码如图所示:
这种修改的方法,甚至连页面都无需更改,的确是非常方便快捷,大家可以试一下,直接可以登录。但这时出了一个新问题,如果我知道这个链接是否可以跳过登录界面呢,答案是一定的,我们清除缓存,访问链接 http://127.0.0.1:8000/event_manage/,发现是下面的页面:
这里没有获取到用户信息,但是却访问了相关页面,解决的方法是在当前页面上加一行语句,写明这个页面需要登录才可以访问。
from django.contrib.auth.decorators import login_required
@login_required
代码截图如下:
这时直接访问页面会报错 404,如下图:
但是这里貌似暴露了链接,我们最好把url也一并指引到默认页面上,于是做加一条路由实现跳转,这个是在根目录下的urls.py文件进行修改:
re_path('accounts/login/*', index),
然后再访问那个页面,就被强制跳转到默认的登录页面了
遗憾是URL依然是原来的url,只是内容跳转了,这个事做个记录以后添加。