本教程为系列教程,为方便阅读,每篇教程开头列出所有教程的目录索引:css
用户注册就是建立用户对象,将用户的我的信息保存到数据库里。回顾一下 Django 的 MVT 经典开发流程,对用户注册功能来讲,首先建立用户模型(M),这一步咱们已经完成了。编写注册视图函数(V),并将为视图函数绑定对应的 URL。编写注册模板(T),模板中提供一个注册表单给用户。Django 用户系统内置了登陆、修改密码、找回密码等视图,可是惟独用户注册的视图函数没有提供,这一部分须要咱们本身来写。html
Django 已经内置了一个用户注册表单:django.contrib.auth.forms.UserCreationForm,不过这个表单的一个小问题是它关联的是 django 内置的 User 模型,从它的源码中能够看出:python
class UserCreationForm(forms.ModelForm):
...
class Meta:
model = User
fields = ("username",)
field_classes = {'username': UsernameField}复制代码
问题就出在内部类 Meta
的 model
属性,它的值对应的是 auth.User,所以没法用于咱们自定义的 User 模型。好在表单实际上就是一个 Python 类,所以咱们能够继承它,对它作一点小小的修改就能够了。git
表单的代码一般写在 forms.py 文件里,所以在 users 应用下新建一个 forms.py 文件用于存放表单代码,而后写上以下代码:github
users/forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import User
class RegisterForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = ("username", "email")复制代码
UserCreationForm
的 Meta
内部类下的 model
属性对应的是 auth.User 模型。而 RegisterForm
经过覆写父类 model
属性的值,将其改成 users.User。数据库
此外 fields
用于指定表单的字段,这些指定的字段在模板中会被渲染成表单控件(即一些 <input>
等表单控件)。 UserCreationForm
中只指定了 fields = ("username",)
,即用户名,此外还有两个字段密码和确认密码在 UserCreationForm
的属性中指定。因此默认的表单渲染后只有用户名(username)、密码、确认密码三个表单控件。咱们还但愿用户注册时提供邮箱地址,因此在 fields
中增长了 email 字段。django
注意:虽然 model
属性的值都被指定为 User,但一个是 auth.User,另外一个是 users.User。浏览器
首先来分析一下注册函数的逻辑。用户在注册表单里填写注册信息,而后经过表单将这些信息提交给服务器。视图函数从用户提交的数据提取用户的注册信息,而后验证这些数据的合法性。若是数据合法,就新建一个用户对象,将用户的数据保存到数据库,不然就将错误信息返回给用户,提示用户对提交的信息进行修改。过程就是这么简单,下面是对应的代码(视图函数的代码一般写在 views.py 文件里):安全
users/views.py
from django.shortcuts import render, redirect
from .forms import RegisterForm
def register(request):
# 只有当请求为 POST 时,才表示用户提交了注册信息
if request.method == 'POST':
# request.POST 是一个类字典数据结构,记录了用户提交的注册信息
# 这里提交的就是用户名(username)、密码(password)、邮箱(email)
# 用这些数据实例化一个用户注册表单
form = RegisterForm(request.POST)
# 验证数据的合法性
if form.is_valid():
# 若是提交数据合法,调用表单的 save 方法将用户数据保存到数据库
form.save()
# 注册成功,跳转回首页
return redirect('/')
else:
# 请求不是 POST,代表用户正在访问注册页面,展现一个空的注册表单给用户
form = RegisterForm()
# 渲染模板
# 若是用户正在访问注册页面,则渲染的是一个空的注册表单
# 若是用户经过表单提交注册信息,可是数据验证不合法,则渲染的是一个带有错误信息的表单
return render(request, 'users/register.html', context={'form': form})复制代码
注意以上视图是处理表单的经典流程,即:bash
def form_process_view(request):
if request.method == 'POST':
# 请求为 POST,利用用户提交的数据构造一个绑定了数据的表单
form = Form(request.POST)
if form.is_valid():
# 表单数据合法
# 进行其它处理...
# 跳转
return redirect('/')
else:
# 请求不是 POST,构造一个空表单
form = Form()
# 渲染模板
# 若是不是 POST 请求,则渲染的是一个空的表单
# 若是用户经过表单提交数据,可是数据验证不合法,则渲染的是一个带有错误信息的表单
return render(request, 'template.html', context={'form': form})复制代码
以上逻辑代码稍加修改就能够应用于各类表单处理。
视图函数须要和对应的 URL 绑定,这样当用户访问某个 URL 时,Django 才知道调用哪一个视图函数处理用户请求。首先在 users 应用下新建一个 urls.py 文件用于设置注册视图函数的 URL 模式。
users/urls.py
from django.conf.urls import url
from . import views
app_name = 'users'
urlpatterns = [
url(r'^register/', views.register, name='register'),
]复制代码
app_name = 'users'
为这个 urls 模块设置命名空间。关于 URL 模式的设置若是不明白的话请参考相关基础教程,这里再也不赘述。
接下来须要在工程的 urls.py 文件里包含 users 应用的 URL 模式。打开 django_auth_example/ 目录下的 urls.py 文件,将 users.urls.py 包含进来:
django_auth_example/urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 别忘记在顶部引入 include 函数
url(r'^users/', include('users.urls')),
]复制代码
咱们在视图函数中渲染了 users/register.html,不过目前这个模板文件还不存在,咱们这就来建立它。我习惯喜欢将模板文件放在项目根目录(manage.py 所在目录)的 templates/ 目录下,而后在 templates/ 目录下再新建各个和应用同名的文件夹,用于存放该应用下的模板文件。固然模板放在哪里是可有可无的,具体视项目而定,只要经过配置模板路径使 Django 可以找到模板文件便可。
按照个人习惯,先在项目根目录(manage.py 所在目录)新建一个 templates/ 目录,而后在 templates/ 目录下新建一个 users 目录,用于存放 users 应用的相关模板文件。而后在 users/ 目录下新建一个 register.html 模板文件(注意是 templates/ 下的 users/ 目录,不是 users 应用目录)。此时目录结构变为:
django_auth_example/
manage.py
django_auth_example/
__init__.py
settings.py
urls.py
wsgi.py
templates/
users/
register.html复制代码
接着须要在 settings.py 里设置 templates/ 所在路径,在 settings.py 找到 TEMPLATES
选项,它的内容是这样的:
django_auth_example/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]复制代码
其中 DIRS
就是设置模板的路径,在 [] 中写入 os.path.join(BASE_DIR, 'templates')
,即像下面这样:
django_auth_example/settings.py
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
...
},
]复制代码
这里 BASE_DIR
是 settings.py 在配置开头前面定义的变量,记录的是工程根目录 django_auth_example/ 的值(注意是最外层的 django_auth_example/ 目录)。在这个目录下有模板文件所在的目录 templates/,因而利用os.path.join
把这两个路径连起来,构成完整的模板路径,Django 就知道去这个路径下面找咱们的模板了。
接下来就是在 register.html 模板中渲染表单了,具体代码以下:
templates/users/register.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>注册</title>
<link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css">
<style> .errorlist { color: red; } </style>
</head>
<body>
<div class="flex-center">
<div class="container">
<div class="flex-center">
<div class="unit-1-2 unit-1-on-mobile">
<h3>注册</h3>
<form class="form" action="{% url 'users:register' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% if field.help_text %}
<p class="help text-small text-muted">{{ field.help_text|safe }}</p>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">注册</button>
</form>
<div class="flex-center top-gap text-small">
<a href="login.html">已有帐号登陆</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>复制代码
为了使注册页面更加美观,我引入了 mobi.css 提供样式支持。其它的代码请忽略,重点只关注表单部分:
<form class="form" action="{% url 'users:register' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% if field.help_text %}
<p class="help text-small text-muted">{{ field.help_text|safe }}</p>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">注册</button>
</form>复制代码
在 Django 中使用表单,必须注意如下几点:
register
进行处理。这里咱们使用了 {% url %} 模板标签,防止 URL 硬编码。关于 {% url %} 模板标签,能够看这篇文章中的介绍 博客文章详情页。接下来就是表单的控件部分。对表单 form(这是一个模板变量,是 RegisterForm
的一个实例,咱们在 register
视图函数中将它传递给模板的。)进行循环就能够获得表单的各个控件:
例如 RegisterForm
表单有用户名字段,渲染的表单控件为:
<label for="id_username">用户名:</label><!-- 对应 {{ field.label_tag }} -->
<input type="text" name="username" id="id_username" autofocus required maxlength="150" /><!-- 对应 {{ field }} -->
<p class="help text-small text-muted">必填。150个字符或者更少。包含字母,数字和仅有的@/./+/-/_符号。</p><!-- 对应 {{ field.help_text }} -->复制代码
你能够按 F12 看看表单的源代码,对比一下表单控件是哪一部分渲染而成的。这种表单渲染方式是一种比较通用的作法,你能够把它当作一个模板,稍做修改就能够应用与其它须要渲染表单的模板中。
OK,运行开发服务器,访问 http://127.0.0.1:8000/users/register/,能够看到渲染的用户注册表单了。
你能够尝试注册一个用户,或者尝试故意输错一些信息,看看表单渲染的错误信息是什么样的,好比我故意输入两次不一样的密码,获得一个错误信息提示:
若是表单数据没有错误,提交表单后就会跳转到首页,因为咱们没有写任何处理首页的视图函数,因此获得一个 404 错误。不过没有关系,我么你如今只关心用户是否注册成功。那么怎么查看用户是否已经注册成功呢?能够去 Django Admin 后台看看是否有用户新注册的数据。为了在 Admin 后台查看用户数据,首先须要注册用户模型。打开 users/admin.py 文件,在里面注册 users.User 模型:
users/admin.py
from django.contrib import admin
from .models import User
admin.site.register(User)复制代码
为了进入后台,还要建立一个超级管理员用户,使用 python manage.py createsuperuser
建立一个管理员帐户便可。若是你不知道怎么建立,请参照 在 Django Admin 后台发布文章 中的说明。
浏览器输入 http://127.0.0.1:8000/admin/,登陆管理员帐户,能够查看到注册的用户信息了,好比在个人后台能够看到三个用户:
其中有一个是使用 createsuperuser 命令建立的管理员帐户,另外两个是注册的新用户。
至此,注册功能已经完成了。用户注册后就要登陆,接下来就是如何提供用户登陆功能了。
本教程的示例项目代码位于 GitHub:Django Auth Example。
若是遇到问题,请经过下面的方式寻求帮助。
更多 Django 相关教程,请访问个人我的博客:追梦人物的博客。