本教程爲系列教程,爲方便閱讀,每篇教程開頭列出所有教程的目錄索引: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 相關教程,請訪問個人我的博客:追夢人物的博客。