引言
在利用python的django框架开发一个web项目时,我们都需要使用注册、登录、注销等用户方面的功能。
当然我们也可以完全手动去实现这些功能,但是django已经帮大家定义这方面的逻辑,这篇文章旨在帮大家熟悉其中的逻辑。主要记录的是博主实现过程中的一些步骤以及问题。不妥之处请大家多多指教。
1、mysql数据库
竟然是用户登录验证,肯定是需要数据库存储数据。利用forms实现登录时,不需要用户自己去创建user表。所有数据存储在autho_user表中。如下图所示(这些表都是django自动创建的)。
我们再看一下auth_user表结构,里面已经有很多字段了。如下图中,除去username与password,都是django自带的。当然我们也可以添加需要的字段,比如username与password。下面告诉大家如何添加字段。
要实现添加字段,首先在自己定义的app下新建一个forms.py文件。
代码读起来不难,但如果独立实现难度很大。建议大家用的时候再去查资料吧。
顺便说一句,本次只实现登录功能,并不包括注册功能。所以在登录功能实现之前,我们要先向auth_user表中添加几条用户信息。理论上通过mysql命令应该能实现该需求,但是回到auth_user的表结构,里面有许多字段我们都不熟悉,操作起来不是很方面。楼主自己也折腾了好久。现在告诉大家一个很简单的方法。(用python console实现)
很简单,不是么。其实,django内部还是用了mysql命令。现在我把第三行红字粘出来给大家看下。就是插入的mysql语句嘛。建议大家用这个方法吧。简单粗暴。
2018-09-14 16:01:06,171 [MainThread:140633755756288] [django.db.backends:111] [utils:execute] [DEBUG]- (0.001) INSERT INTO `auth_user` (`password`, `last_login`, `is_superuser`, `username`, `first_name`, `last_name`, `email`, `is_staff`, `is_active`, `date_joined`) VALUES ('pbkdf2_sha256$120000$C7tnl14cLisJ$+vN6Vtfkw4d+Y+gWUw5DTraUgW6FSyBrYNkEy9/ugxE=', NULL, 0, 'phoenix', '', '', '', 0, 1, '2018-09-14 16:01:06.041147'); args=['pbkdf2_sha256$120000$C7tnl14cLisJ$+vN6Vtfkw4d+Y+gWUw5DTraUgW6FSyBrYNkEy9/ugxE=', None, False, 'phoenix', '', '', '', False, True, '2018-09-14 16:01:06.041147']
2、HTML的form
正常的HTML的form表单应该长这个样:
<form method="post" action="loginAction">
{% csrf_token %}
<label id="label_un">用户名/username</label><br/>
<input type="text" id = 'username' name="username"><br/>
<label id="label_pw">密码/password</label><br/>
<input type="password" name="password"><br/>
<button type="submit" id="login">登陆 </button>
</form>
我们需要的表单应该是这样的:
<form method="post" action="login">{% csrf_token %}
<label id="label_un">用户名/username</label><br/>
{{ loginform.username }}<br/>
<label id="label_pw">密码/password</label><br/>
{{ loginform.password }}<br/>
<button type="submit" id="login">登陆 </button>
</form>
简单解释一下代码,其中html部分都是大家熟悉的没啥解释的。{{}}是python用来取值的。这里面的loginform是我们之前定义类LoginForm的对象,分别取username和password值,取代之前前端的文本框。看起来很简单,因为之前在定义LoginForm类已经写过了文本框的一些属性了。
当我们完成了这个功能,在浏览器访问登录界面时,form表单的代码是这样的:
<form method="post" action="login"><input type="hidden" name="csrfmiddlewaretoken" value="kMao3kU68rKXmNxArp1wSBbEy1PS6TMapW76nPf7CUWI9tGNvUL9P7XbUceaga2v">
<label id="label_un">用户名/username</label><br/>
<input type="text" name="username" placeholder="username" required id="id_username"><br/>
<label id="label_pw">密码/password</label><br/>
<input type="password" name="password" placeholder="password" required id="id_password"><br/>
<button type="submit" id="login">登陆 </button>
</form>
python后端实现
登录逻辑的代码如下所示。简单解释下。
请先忽略异常处理部分。良好的代码风格从处理异常开始。大家感兴趣可以自己去查查资料。
- 首先获取请求方式,如果不是POST方式,即不是通过表单提交过来的,比如我们在浏览器输入localhost:8000/login,此时,也调用该处理逻辑。此时,我们应该创建一个LoginForm对象,并返回到login.html界面,该界面会加载出html内容,包括表单。
- 当用户输入完用户名、密码点击提交时,此时请求方式即为POST方式。具体处理逻辑在代码中有所体现,读起来不是很难。注意alogin方法,其实就是auth自带的login方法。
- 如果表单对象或用户验证失败都跳转到登录失败界面;登录成功则通过重定向的方式到主页。
- 顺便说一句,auth的login方法内部也利用session存储 了数据,但是是用户ID,backends以及session_auth_hash,大家可以通过ctrl加鼠标左键单击方法名去查看源码。所以,如果我们要记住用户名,还需要自己实现session。
from django.shortcuts import render,redirect
from .forms import LoginForm
from django.contrib.auth import login as alogin, authenticate
def login(request):
try:
if request.method == 'POST':
loginform = LoginForm(request.POST)
if loginform.is_valid():
username = loginform.cleaned_data['username']
password = loginform.cleaned_data['password']
user = authenticate(username=username, password=password)
if user:
user.backend = 'django.contrib.auth.backends.ModelBackend'
alogin(request, user)
request.session['username'] = username
return redirect(index)
else:
return render(request, 'poas/failure.html')
else:
return render(request, 'poas/failure.html', {'reason': loginform.errors})
else:
loginform = LoginForm()
except Exception as e:
logging.error(e)
print(e)
return render(request, 'poas/login.html',{'loginform': loginform})
总结
至此,登录的功能基本上实现了。再学习django表单之前,我是自己定义数据库表、设置验证逻辑等实现登录功能。再看了这方面的知识后,我选择了自己动手重构代码。虽然用起来很生疏,但是磕磕碰碰总算实现了。自我感觉只要大家自己肯动手,就一定能解决任何问题。与诸君共勉,写的不好,请多多指教。谢谢!