既然有登录登出,那么用户的注册肯定也是少不了的。
注册表单类
用户注册时会用到表单来提交账号、密码等数据,所以需要写注册用的表单/userprofile/forms.py
:
/userprofile/forms.py
...
# 注册用户表单
class UserRegisterForm(forms.ModelForm):
# 复写 User 的密码
password = forms.CharField()
password2 = forms.CharField()
class Meta:
model = User
fields = ('username', 'email')
# 对两次输入的密码是否一致进行检查
def clean_password2(self):
data = self.cleaned_data
if data.get('password') == data.get('password2'):
return data.get('password')
else:
raise forms.ValidationError("密码输入不一致,请重试。")
上一章也讲过,对数据库进行操作的表单应该继承forms.ModelForm
,可以自动生成模型中已有的字段。
这里我们覆写了password
字段,因为通常在注册时需要重复输入password
来确保用户没有将密码输入错误,所以覆写掉它以便我们自己进行数据的验证工作。def clean_password2()
中的内容便是在验证密码是否一致了。def clean_[字段]
这种写法Django会自动调用,来对单个字段的数据进行验证清洗。
覆写某字段之后,内部类class Meta
中的定义对这个字段就没有效果了,所以fields
不用包含password
。
需要注意:
- 验证密码一致性方法不能写
def clean_password()
,因为如果你不定义def clean_password2()
方法,会导致password2中的数据被Django判定为无效数据从而清洗掉,从而password2
属性不存在。最终导致两次密码输入始终会不一致,并且很难判断出错误原因。 - 从POST中取值用的
data.get('password')
是一种稳妥的写法,即使用户没有输入密码也不会导致程序错误而跳出。前面章节提取POST数据我们用了data['password']
,这种取值方式如果data中不包含password
,Django会报错。另一种防止用户不输入密码就提交的方式是在表单中插入required
属性,后面会讲到。
视图函数
编写注册的视图/userprofile/views.py
:
/userprofile/views.py
# 引入 UserRegisterForm 表单类
from .forms import UserLoginForm, UserRegisterForm
# 用户注册
def user_register(request):
if request.method == 'POST':
user_register_form = UserRegisterForm(data=request.POST)
if user_register_form.is_valid():
new_user = user_register_form.save(commit=False)
# 设置密码
new_user.set_password(user_register_form.cleaned_data['password'])
new_user.save()
# 保存好数据后立即登录并返回博客列表页面
login(request, new_user)
return redirect("article:article_list")
else:
return HttpResponse("注册表单输入有误。请重新输入~")
elif request.method == 'GET':
user_register_form = UserRegisterForm()
context = { 'form': user_register_form }
return render(request, 'userprofile/register.html', context)
else:
return HttpResponse("请使用GET或POST请求数据")
逻辑上结合了发表文章视图和用户登录视图,没有新的知识。
用户在注册成功后会自动登录并返回博客列表页面。
模板和url
表单有关的模板文件我们也很熟悉了,新建/templates/userprofile/register.html
:
/templates/userprofile/register.html
{% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-12">
<br>
<form method="post" action=".">
{% csrf_token %}
<!-- 账号 -->
<div class="form-group col-md-4">
<label for="username">昵称</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<!-- 邮箱 -->
<div class="form-group col-md-4">
<label for="email">Email</label>
<input type="text" class="form-control" id="email" name="email">
</div>
<!-- 密码 -->
<div class="form-group col-md-4">
<label for="password">设置密码</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<!-- 确认密码 -->
<div class="form-group col-md-4">
<label for="password2">确认密码</label>
<input type="password" class="form-control" id="password2" name="password2" required>
</div>
<!-- 提交按钮 -->
<button type="submit" class="btn btn-primary">提交</button>
</form>
</div>
</div>
</div>
{% endblock content %}
上面的模板文件中,我们在昵称、密码input
标签中添加了required
属性(前面提到过)。如果用户不填写带有required
属性的字段,表单就不能提交,并提示用户填写。实际上前面学习的很多表单都可以添加required
属性来提前验证数据的有效性。
注册的入口你可以放在任何喜欢的地方。本文放在登录页面中/templates/userprofile/login.html
:
/templates/userprofile/login.html
...
<div class="col-12">
<br>
<h5>还没有账号?</h5>
<h5>点击<a href='{% url "userprofile:register" %}'>注册账号</a>加入我们吧!</h5>
<br>
<form method="post" action=".">
...
</form>
</div>
...
最后就是在app中配置路由文件/userprofile/urls.py
了:
/userprofile/urls.py
...
urlpatterns = [
...
# 用户注册
path('register/', views.user_register, name='register'),
]
测试
运行服务器,进入到登录页面,多了注册的提示:
点击注册账号进入注册页面:
填写好表单后提交(Email地址是可以为空的):
成功登录并返回了博客列表,功能完成。
总结
本章用到了表单类、对数据进行验证清洗等知识,完成了用户的注册功能。
接下来学习如何实现删除已有的用户。
- 有疑问请在杜赛的个人网站留言,我会尽快回复。
- 或Email私信我:dusaiphoto@foxmail.com
- 项目完整代码:Django_blog_tutorial
转载请告知作者并注明出处。