上篇我们实现了用户的登录和登出。
本篇我们完善用户管理的另一个重要功能:注册。
编写注册表单类
用户注册时会用到表单来提交账号、密码等数据,所以需要写注册用的表单/userprofile/forms.py
:
# 注册用户表单class UserRegisterForm(forms.ModelForm):# 复写 User 的密码password = forms.CharField()password2 = forms.CharField()class Meta:model = Userfields = ('username', 'email')# 对两次输入的密码是否一致进行检查def clean_password2(self):data = self.cleaned_dataif 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
:
# 用户注册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("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
表单有关的模板文件我们也很熟悉了,这里涉及两个模板编写和处理。
1、增加注册页面
新建templates/userprofile/register.html
{% extends "base.html" %} {% load static %}{% block title %} 注册 {% endblock title %}{% block content %}<div class="container"><div class="row justify-content-md-center"><div class="col-md-6"><br><form method="post" action=".">{% csrf_token %}<!-- 账号 --><div class="form-group"><label for="username">昵称</label><input type="text" class="form-control" id="username" name="username" required></div><!-- 邮箱 --><div class="form-group"><label for="email">Email</label><input type="text" class="form-control" id="email" name="email"></div><!-- 密码 --><div class="form-group"><label for="password">设置密码</label><input type="password" class="form-control" id="password" name="password" required></div><!-- 确认密码 --><div class="form-group"><label for="password2">确认密码</label><input type="password" class="form-control" id="password2" name="password2" required></div><br><!-- 提交按钮 --><button type="submit" class="btn btn-primary btn-block">提交</button></form></div></div></div>{% endblock content %}
上面的模板文件中,我们在昵称、密码input
标签中添加了required
属性(前面提到过)。如果用户不填写带有required
属性的字段,表单就不能提交,并提示用户填写。实际上前面学习的很多表单都可以添加required
属性来提前验证数据的有效性。
2、增加注册入口
在登录页面中增加注册入口/templates/userprofile/login.html
:
<div class="form-group"><br><h5>还没有账号?</h5><h5>点击<a href='{% url "register" %}'>注册账号</a>加入我们吧!</h5><br></div>
最后就是配置路由文件了django4blog/urls.py
:
urlpatterns = [path('admin/', admin.site.urls),path('hello/', article.views.hello),re_path(r'^$', article.views.article_list),path('list/', article.views.article_list, name='list'), # 展示文章path('detail/<int:id>/', article.views.article_detail, name='detail'), # 文章详情path('create/', article.views.article_create, name='create'), # 写文章path('delete/<int:id>/', article.views.article_delete, name='delete'),# 删除文章path('update/<int:id>/', article.views.article_update, name='update'), # 更新文章path('login/', userprofile.views.user_login, name='login' ),path('logout/', userprofile.views.user_logout, name='logout' ),# 增加注册管理path('register/', userprofile.views.user_register, name='register' ),]
测试
运行服务器,进入到登录页面,多了注册的提示:
点击注册账号进入注册页面:
填写好表单后提交(Email地址是可以为空的):
成功登录并返回了博客列表,功能完成。
总结
本章用到了表单类、对数据进行验证清洗等知识,完成了用户的注册功能。
至此,核心的用户登录,登出,注册功能我们已经都基本实现的功能。
接下来我们将学习另外一个重要模块:评论管理。