在第 9 章,我们自己动手创建视图、模板和 URL 映射,为 Rango 应用添加了登录和注册功能。然而,这些功能在 Web 应用中太常见了,因此别的开发者已经创建了众多拿来即用的扩展应用,能为 Django 项目提供登录、注册、一步和两步身份验证、密码修改、密码重设等功能。本章将使用 django-registration-redux 包实现这些功能。
为此,我们要重构代码,删掉前面实现的登录和注册功能,然后配置项目,使用
django-registration-redux 应用。读完本章后,你将掌握使用外部应用的方法,一窥整个过程是多么简单。
11.1 安装和设置
- 首先,使用 pip 在你的虚拟环境中安装 django-registration-redux 1.4 版:$ pip install -U django-registration-redux==1.4
- 然后告诉 Django,我们想使用这个应用。打开 settings.py 文件,更新 INSTALLED_APPS 列表:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rango',
'registration' # 增加 registration 包 ]
- 既然打开 settings.py 文件了,顺便添加这个包所需的几个配置变量:
#添加registration的环境变量
# 设为 True,允许用户注册
REGISTRATION_OPEN = True
# 留一周的激活时间;当然,也可以设为其他值
ACCOUNT_ACTIVATION_DAYS = 7
# 设为 True,注册后自动登录
REGISTRATION_AUTO_LOGIN = True
# 登录后呈现给用户的页面
LOGIN_REDIRECT_URL = '/rango/'
# 未登录以及访问需要验证身份的页面时重定向的页面
LOGIN_URL = '/accounts/login/'
- 接下来,打开 tango_with_django_project/urls.py 文件,更新 urlpatterns,引入 registration 包的URL 映射:
url(r'^accounts/', include('registration.backends.simple.urls')),
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^rango/',include('rango.urls')),
url(r'^admin/', admin.site.urls),
url(r'^accounts/',include('registration.backends.simple.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
11.2 各项操作的 URL 映射
django-registration-redux 包提供了多种操作。registration.backend.simple.urls 中包含下述映射:
❏ 注册 → /accounts/register/
❏ 注册完成 → /accounts/register/complete/
❏ 登录 → /accounts/login/
❏ 退出 → /accounts/logout/
❏ 修改密码 → /password/change/
❏ 重设密码 → /password/reset/
registration.backends.default.urls 还提供了两步注册过程中激活账户这一步:
❏ 激活 → activate/<activation_key>/
❏ 成功激活 → activate/complete/
❏ 激活电子邮件
• 激活邮件的正文(一个文本文件)
• 激活邮件的主题(一个文本文件)
下面是关键所在。虽然 django-registration-redux 包提供了上述丰富的功能,但是没有提供模板,因为每个应用都有自己的结构和外观设计。所以,接下来我们要创建各视图的模板。
11.3 创建模板
django-registration-redux 包的快速入门指南简要说明了需要哪些模板,但是没有明确指明各模板的内容。你可以自行试验,写出所需的代码。不过我们可以走个捷径,参考 Anders Hofstee 编写的模板。
首先,在 templates 目录中新建一个目录,命名为 registration。django-registration-redux 应用相关的模板都保存在这个目录中。
注册页面的模板
在 templates/registration 目录中新建 registration_form.html 文件,写入下述代码:
{
% extends "rango/base.html" %}
{
% block body_block %}
<h1>Register Here</h1>
<form method="post" action=".">
{
% csrf_token %}
{
{
form.as_p }}
<input type="submit" value="Submit" />
</form>
{
% endblock %}
注册完成页面的模板
在 templates/registration 目录中新建 registration_complete.html 文件,写入下述代码:
{
% extends "rango/base.html" %}
{
% block body_block %}
<h1>Registration Complete</h1>
<p>You are now registered</p>
{
% endblock %}
退出页面的模板
在 templates/registration 目录中新建 logout.html 文件,写入下述代码:
{
% extends "rango/base.html" %}
{
% block body_block %}
<h1>Logged Out</h1>
<p>You are now logged out.</p>
{
% endblock %}
试一下注册过程
启动 Django 开发服务器,访问 http://127.0.0.1:8000/accounts/register/。注意,注册表单中有两个密码字段,用于确认密码。自己注册试试,两次输入不同的密码。
这只是整个过程的其中一步。
重构项目
接下来更新 base.html 模板,使用新的 URL 和视图。
❏ 把注册链接改为 < a href="{% url ‘registration_register’ %}">。
❏ 把登录链接改为 < a href="{% url ‘auth_login’ %}">。
❏ 把退出链接改为 < a href="{% url ‘auth_logout’ %}?next=/rango/">。
❏ 在 settings.py 文件中,把 LOGIN_URL 改为 ‘/accounts/login/’。
注意,退出 URL 的后面有 ?next=/rango/,这样退出后才会重定向到 Rango 应用的首页。否则,退出后将重定向到退出页面,这样不太友好。
接下来要停用 Rango 应用中的注册、登录和退出功能:把相关的 URL 映射、视图和模板删除(或者注释掉)。
修改注册流程
现在,用户成功注册后会转到注册完成页面。这样感觉有点多此一举。因此,我们修改一下,转向首页。为此要覆盖 registration.backends.simple.views 提供的 RegistrationView。打开 tango_with_django_project/urls.py 文件,导入 RegistrationView,然后定义一个 RegistrationView 的子类。
from registration.backends.simple.views import RegistrationView
# 定义一个类
# 用户成功注册后重定向到首页
class MyRegistrationView(RegistrationView):
def get_success_url(self, user):
return '/rango/'
然后修改 Django 项目的 urls.py 模块中的 urlpatterns 列表,在 accounts 模式前添加下述代码,以便在其他 accounts/ URL 之前匹配 accounts/register。注意,修改的不是 rango 目录中的 urls.py模块。
url(r'^accounts/register/$',MyRegistrationView.as_view(),name='registration_register'),
这样修改之后,成功注册后便会重定向到我们指定的页面。
11.4 练习
❏ 为用户提供修改密码功能。
❏ 提示:参考 Anders Hofstee 编写的模板。
❏ 提示:修改密码的 URL 是 accounts/password/change/,指明密码已修改的 URL 是 accounts/password/change/done/。
小结:
- 遇到问题:cannot import name ‘python_2_unicode_compatible’ from ‘django.utils.encoding’