4 創(chuàng)建一個(gè)社交網(wǎng)站
在上一章中,你學(xué)習(xí)了如何創(chuàng)建站點(diǎn)地圖和訂閱,并且為博客應(yīng)用構(gòu)建了一個(gè)搜索引擎。在這一章中,你會開發(fā)一個(gè)社交應(yīng)用。你會為用戶創(chuàng)建登錄,登出,編輯和修改密碼的功能。你會學(xué)習(xí)如何為用戶創(chuàng)建自定義的個(gè)人資料,并在網(wǎng)站中添加社交認(rèn)證。
本章會涉及以下知識點(diǎn):
- 使用認(rèn)證框架
- 創(chuàng)建用戶注冊視圖
- 用自定義個(gè)人資料模型擴(kuò)展
User
模型 - 用
python-social-auth
添加社交認(rèn)證
讓我們從創(chuàng)建新項(xiàng)目開始。
4.1 創(chuàng)建一個(gè)社交網(wǎng)站項(xiàng)目
我們將會創(chuàng)建一個(gè)社交應(yīng)用,讓用戶可以分享他們在Internet上發(fā)現(xiàn)的圖片。我們需要為該項(xiàng)目構(gòu)建以下元素:
- 一個(gè)認(rèn)證系統(tǒng),用于用戶注冊,登錄,編輯個(gè)人資料,修改或重置密碼
- 一個(gè)關(guān)注系統(tǒng),允許用戶互相關(guān)注
- 顯示分享的圖片,并實(shí)現(xiàn)一個(gè)書簽工具,讓用戶可以分享任何網(wǎng)站的圖片
- 每個(gè)用戶的活動(dòng)信息,讓用戶可以看到他關(guān)注的用戶上傳的內(nèi)容
本章討論第一點(diǎn)。
4.1.1 啟動(dòng)社交網(wǎng)站項(xiàng)目
打開終端,使用以下命令為項(xiàng)目創(chuàng)建一個(gè)虛擬環(huán)境,并激活:
mkdir env
virtualenv env/bookmarks
source env/bookmarks/bin/activate
終端會如下顯示你激活的虛擬環(huán)境:
(bookmarks)laptop:~ zenx$
使用以下命令,在虛擬環(huán)境中安裝Django:
pip install Django
執(zhí)行以下命令創(chuàng)建一個(gè)新項(xiàng)目:
django-admin startproject bookmarks
創(chuàng)建初始項(xiàng)目結(jié)構(gòu)之后,使用以下命令進(jìn)入項(xiàng)目目錄,并創(chuàng)建一個(gè)account
的新應(yīng)用:
cd bookmarks/
django-admin startapp account
通過把該應(yīng)用添加到settings.py
文件的INSTALLED_APPS
中,來激活它。把它放在INSTALLED_APPS
列表的最前面:
INSTALLED_APPS = (
'account',
# ...
)
執(zhí)行下面的命令,同步INSTALLED_APPS
設(shè)置中默認(rèn)應(yīng)用的模型到數(shù)據(jù)庫中:
python manage.py migrate
接下來,我們用authentication
框架在項(xiàng)目中構(gòu)建一個(gè)認(rèn)證系統(tǒng)。
4.2 使用Django認(rèn)證框架
Django內(nèi)置一個(gè)認(rèn)證框架,可以處理用戶認(rèn)證,會話,權(quán)限和用戶組。該認(rèn)證系統(tǒng)包括常見的用戶操作視圖,比如登錄,登出,修改密碼和重置密碼。
認(rèn)證框架位于django.contrib.auth
中,并且被其它Django contrib
包使用。記住,你已經(jīng)在第一章中使用過認(rèn)證框架,為博客應(yīng)用創(chuàng)建了一個(gè)超級用戶,以便訪問管理站點(diǎn)。
當(dāng)你使用startproject
命令創(chuàng)建新Django項(xiàng)目時(shí),認(rèn)證框架已經(jīng)包括在項(xiàng)目的默認(rèn)設(shè)置中。它由django.contrib.auth
應(yīng)用和以下兩個(gè)中間件(middleware)類組成(這兩個(gè)中間類位于項(xiàng)目的MIDDLEWARE_CLASSES
設(shè)置中):
-
AuthenticationMiddleware
:使用會話管理用戶和請求 -
SessionMiddleware
:跨請求處理當(dāng)前會話
一個(gè)中間件是一個(gè)帶有方法的類,在解析請求或響應(yīng)時(shí),這些方法在全局中執(zhí)行。你會在本書的好幾個(gè)地方使用中間件類。你會在第13章學(xué)習(xí)如何創(chuàng)建自定義的中間件。
該認(rèn)證框架還包括以下模塊:
-
User
:一個(gè)有基礎(chǔ)字典的用戶模型;主要字段有:username
,password
,email
,first_name
,last_name
和is_active
。 -
Group
:一個(gè)用于對用戶分類的組模型。 -
Permission
:執(zhí)行特定操作的標(biāo)識。
該框架還包括默認(rèn)的認(rèn)證視圖和表單,我們之后會學(xué)習(xí)。
4.2.1 創(chuàng)建登錄視圖
我們從使用Django認(rèn)證框架允許用戶登錄網(wǎng)站開始。我們的視圖要執(zhí)行以下操作來登錄用戶:
- 通過提交表單獲得用戶名和密碼。
- 對比數(shù)據(jù)庫中的數(shù)據(jù),來驗(yàn)證用戶。
- 檢查用戶是否激活。
- 用戶登錄,并開始一個(gè)認(rèn)證的會話(authenticated session)。
首先,我們將創(chuàng)建一個(gè)登錄表單。在account
應(yīng)用目錄中創(chuàng)建forms.py
文件,添加以下代碼:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
該表單用于在數(shù)據(jù)庫用驗(yàn)證用戶。注意,我們使用PasswordInput
組件來渲染包括type="password"
屬性的HTML input
元素。編輯account
應(yīng)用的views.py
文件,添加以下代碼:
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from .forms import LoginForm
def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'],
password=cd['password'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled account')
else:
return HttpResponse('Invalid login')
else:
form = LoginForm()
return render(request, 'account/login.html', {'form': form})
這是我們在視圖中所做的基本登錄操作:當(dāng)使用GET
請求調(diào)用user_login
視圖時(shí),我們使用form = LoginForm()
實(shí)例化一個(gè)新的登錄表單,用于在模板中顯示。當(dāng)用戶通過POST
提交表單時(shí),我們執(zhí)行以下操作:
- 使用
form = LoginForm(request.POST)
實(shí)例化帶有提交的數(shù)據(jù)的表單。 - 檢查表單是否有效。如果無效,則在模板中顯示表單錯(cuò)誤(例如,用戶沒有填寫某個(gè)字段)。
- 如果提交的數(shù)據(jù)有效,我們使用
authenticate()
方法,在數(shù)據(jù)庫中驗(yàn)證用戶。該方法接收username
和password
參數(shù),如果用戶驗(yàn)證成功,則返回User
對象,否則返回None
。如果用戶沒有通過驗(yàn)證,我們返回一個(gè)原始的HttpResponse
,顯示一條消息。 - 如果用戶驗(yàn)證成功,我們通過
is_active
屬性檢查用戶是否激活。這是DjangoUser
模型的屬性。如果用戶沒有激活,我們返回一個(gè)HttpResponse
顯示信息。 - 如果是激活的用戶,我們在網(wǎng)站登錄用戶。我們調(diào)用
login()
方法,把用戶設(shè)置在session中,并返回一條成功消息。
注意
authenticate
和login
之間的區(qū)別:authenticate()
方法檢查用戶的認(rèn)證信息,如果正確,則返回User
對象;login()
在當(dāng)前session中設(shè)置用戶。
現(xiàn)在,你需要為該視圖創(chuàng)建URL模式。在account
應(yīng)用目錄中創(chuàng)建urls.py
文件,并添加以下代碼:
from django.conf.urls import url
from . import views
urlpatterns = [
# post views
url(r'^login/$', views.user_login, name='login'),
]
編輯bookmarks
項(xiàng)目目錄中的urls.py
文件,在其中包括account
應(yīng)用的URL模式:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^account/', include('account.urls')),
]
現(xiàn)在可以通過URL訪問登錄視圖了。是時(shí)候?yàn)樵撘晥D創(chuàng)建一個(gè)模板了。因?yàn)樵擁?xiàng)目還沒有模板,所以你可以創(chuàng)建一個(gè)基礎(chǔ)模板,在登錄模板中擴(kuò)展它。在account
應(yīng)用目錄中創(chuàng)建以下文件和目錄:
templates/
account/
login.html
base.html
編輯base.html
文件,添加以下代碼:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/base.css" %}" rel="stylesheet">
</head>
<body>
<div id="header">
<span class="logo">Bookmarks</span>
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
這是網(wǎng)址的基礎(chǔ)模板。跟之前的項(xiàng)目一樣,我們在主模板中包括CSS樣式。該基礎(chǔ)模板定義了title
和content
區(qū)域,可以被從它擴(kuò)展的模板填充內(nèi)容。
讓我們?yōu)榈卿洷韱蝿?chuàng)建模板。打開account/login.html
模板,添加以下代碼:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Log-in</h1>
<p>Please, user the following form to log-in</p>
<form action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Log-in"></p>
</form>
{% endblock %}
該模板包括了在視圖中實(shí)例化的表單。因?yàn)槲覀兊谋韱螘ㄟ^POST
提交,所以我們使用{% csrf_token %}
模板標(biāo)簽進(jìn)行CSRF保護(hù)。你在第2章學(xué)習(xí)了CSRF保護(hù)。
現(xiàn)在數(shù)據(jù)庫中還沒有用戶。首先,你需要?jiǎng)?chuàng)建一個(gè)超級用戶,訪問管理站點(diǎn)來管理其他用戶。打開命令行,執(zhí)行python manage.py createsuperuser
。填寫必需的用戶名,郵箱和密碼。然后使用python manage.py runserver
啟動(dòng)開發(fā)服務(wù)器,并在瀏覽器中打開http://127.0.0.1:8000/admin/
。使用你剛創(chuàng)建的用戶登錄管理站點(diǎn)。你會看到Django管理站點(diǎn)中包括了Django認(rèn)證框架的User
和Group
模型,如下圖所示:
通過管理站點(diǎn)創(chuàng)建一個(gè)新用戶,并在瀏覽器中打開http://127.0.0.1:8000/account/login/
。你會看到包括登錄表單的模板:
現(xiàn)在,提交表單時(shí)不填其中一個(gè)字段。這時(shí),你會看到表單是無效的,并顯示錯(cuò)誤信息,如下圖所示:
如果你輸入一個(gè)不存在的用戶,或者錯(cuò)誤的密碼,你會看到一條Invalid login
消息。
如果你輸入有效的認(rèn)證信息,會看到一條Authenticated successfully
消息,如下圖所示:
4.2.2 使用Django認(rèn)證視圖
Django在認(rèn)證框架中包括了幾個(gè)表單和視圖,你可以直接使用。你已經(jīng)創(chuàng)建的登錄視圖對于理解Django中的用戶認(rèn)證過程是一個(gè)很好的練習(xí)。然而,你在絕大部分情況下可以使用默認(rèn)的Django認(rèn)證視圖。
Django提供了以下視圖處理認(rèn)證:
-
login
:操作一個(gè)登錄表單,并登錄用戶 -
logout
:登出一個(gè)用戶 -
logout_then_login
:登出一個(gè)用戶,并重定向用戶到登錄頁面
Django提供以下視圖處理修改密碼:
-
password_change
:操作一個(gè)修改用戶密碼的表單 -
password_change_done
:修改密碼后,顯示成功頁面
Django還提供以下視圖用于重置密碼:
-
password_reset
:允許用戶重置密碼。它生成一個(gè)帶令牌的一次性鏈接,并發(fā)送到用戶的電子郵箱中。 -
password_reset_done
:告訴用戶,重置密碼的郵件已經(jīng)發(fā)送到他的郵箱中。 -
password_reset_confirm
:讓用戶設(shè)置新密碼。 -
password_reset_complete
:用戶重置密碼后,顯示成功頁面。
創(chuàng)建一個(gè)帶用戶賬戶的網(wǎng)站時(shí),這里列出的視圖會節(jié)省你很多時(shí)間。你可以覆蓋這些視圖使用的默認(rèn)值,比如需要渲染的模板的位置,或者視圖使用的表單。
你可以在這里獲得更多關(guān)于內(nèi)置的認(rèn)證視圖的信息。
4.2.3 登錄和登出視圖
編輯account
應(yīng)用的urls.py
文件,如下所示:
from django.conf.urls import url
from django.contrib.auth.views import login, logout, logout_then_login
from . import views
urlpatterns = [
# previous login view
# url(r'^login/$', views.user_login, name='login'),
# login / logout urls
url(r'^login/$', login, name='login'),
url(r'^logout/$', logout, name='logout'),
url(r'^logout-then-login/$', logout_then_login, name='logout_then_login'),
]
譯者注:Django新版本中,URL模式使用方式跟舊版本不一樣。
我們注釋了之前為user_login
視圖創(chuàng)建的URL模式,使用了Django認(rèn)證框架的login
視圖。
在account
應(yīng)用的templates
目錄中創(chuàng)建一個(gè)registration
目錄。這是Django認(rèn)證視圖的默認(rèn)路徑,它期望你的認(rèn)證模板在這個(gè)路徑下。在新創(chuàng)建的目錄中創(chuàng)建login.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Log-in</h1>
{% if form.errors %}
<p>
Your username and password didn't match.
Please try again.
</p>
{% else %}
<p>Please, user the following form to log-in</p>
{% endif %}
<div class="login-form">
<form action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}" />
<p><input type="submit" value="Log-in"></p>
</form>
</div>
{% endblock %}
這個(gè)login
模板跟我們之前創(chuàng)建那個(gè)很像。Django默認(rèn)使用django.contrib.auth.forms
中的AuthenticationForm
。該表單嘗試驗(yàn)證用戶,如果登錄不成功,則拋出一個(gè)驗(yàn)證錯(cuò)誤。這種情況下,如果認(rèn)證信息出錯(cuò),我們可以在模板中使用{% if form.errors %}
查找錯(cuò)誤。注意,我們添加了一個(gè)隱藏的HTML <input>
元素,用于提交名為next
的變量的值。當(dāng)你在請求中傳遞一個(gè)next
參數(shù)時(shí)(比如,http://127.0.0.1:8000/account/login/?next=/account/
),這個(gè)變量首次被登錄視圖設(shè)置。
next
參數(shù)必須是一個(gè)URL。如果指定了這個(gè)參數(shù),Django登錄視圖會在用戶登錄后,重定義到給定的URL。
現(xiàn)在,在registration
模板目錄中創(chuàng)建一個(gè)logged_out.html
模板,添加以下代碼:
{% extends "base.html" %}
{% block title %}Logged out{% endblock %}
{% block content %}
<h1>Logged out</h1>
<p>You have been successfully logged out. You can <a href="{% url "login" %}">log-in again></a>.</p>
{% endblock %}
用戶登出之后,Django會顯示這個(gè)模板。
為登錄和登出視圖添加URL模式和模板后,網(wǎng)站已經(jīng)可以使用Django認(rèn)證視圖登錄了。
注意,我們在
urlconf
中包含的logout_then_login
視圖不需要任何模板,因?yàn)樗囟x到了登錄視圖。
現(xiàn)在我們開始創(chuàng)建一個(gè)新的視圖,當(dāng)用戶登錄賬號時(shí),用于顯示用戶的儀表盤。打開account
應(yīng)用的views.py
文件,添加以下代碼:
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request,
'account/dashboard.html',
{'section': 'dashboard'})
我們用認(rèn)證框架的login_required
裝飾器裝飾視圖。該裝飾器檢查當(dāng)前用戶是否認(rèn)證。如果是認(rèn)證用戶,它會執(zhí)行被裝飾的視圖。如果不是認(rèn)證用戶,它會重定向用戶到登錄URL,并在登錄URL中帶上一個(gè)名為next
的GET
參數(shù),該參數(shù)是用戶試圖訪問的URL。通過這樣的做法,當(dāng)用戶成功登錄后,登錄視圖會重定向用戶到用戶登錄之前試圖訪問的頁面。記住,我們在登錄模板的表單中添加了一個(gè)隱藏的<input>
元素就是為了這個(gè)目的。
我們還定義了一個(gè)section
變量。我們用這個(gè)變量跟蹤用戶正在查看網(wǎng)站的哪一部分(section)。多個(gè)視圖可能對應(yīng)相同的部分。這是定義每個(gè)視圖對應(yīng)的section的簡便方式。
現(xiàn)在,你需要為儀表盤視圖創(chuàng)建一個(gè)模板。在templates/account/
目錄下創(chuàng)建dashboard.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
{% endblock %}
接著,在account
應(yīng)用的urls.py
文件中,為該視圖添加URL模式:
urlpatterns = [
# ...
url(r'^$', views.dashboard, name='dashboard'),
]
編輯項(xiàng)目的settings.py
文件,添加以下代碼:
from django.core.urlresolvers import reverse_lazy
LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
LOGIN_URL = reverse_lazy('login')
LOGOUT_URL = reverse_lazy('logout')
這些設(shè)置是:
-
LOGIN_REDIRECT_URL
:告訴Django,如果contrib.auth.views.login
視圖沒有獲得next
參數(shù)時(shí),登錄后重定向到哪個(gè)URL -
LOGIN_URL
:重定向用戶登錄的URL(比如使用login_required
裝飾器) -
LOGOUT_URL
:重定向用戶登出的URL
我們使用reverse_lazy()
,通過URL的名字動(dòng)態(tài)創(chuàng)建URL。reverse_lazy()
函數(shù)跟reverse()
函數(shù)一樣逆向URL。當(dāng)你需要在項(xiàng)目URL配置加載之前逆向URL時(shí),可以使用reverse_lazy()
。
讓我們總結(jié)一下,到現(xiàn)在為止,我們做了哪些工作:
- 你在項(xiàng)目中添加了內(nèi)置的Django認(rèn)證登錄和登出視圖
- 你為這兩個(gè)視圖創(chuàng)建了自定義模板,并定義了一個(gè)簡單的視圖,讓用戶登錄后重定向到這個(gè)視圖
- 最后,你配置了設(shè)置,讓Django默認(rèn)使用這些URL
現(xiàn)在,我們需要把登錄和登出鏈接到基礎(chǔ)模板中,把所有功能串起來。
要做到這點(diǎn),我們需要確定,無論當(dāng)前用戶是否登錄,都能顯示適當(dāng)?shù)逆溄印Mㄟ^認(rèn)證中間件,當(dāng)前用戶被設(shè)置在HttpRequest
對象中。你可以通過request.user
訪問。即使用戶沒有認(rèn)證,你也可以找到一個(gè)用戶對象。一個(gè)未認(rèn)證的用戶在request
中是一個(gè)AnonymousUser
的實(shí)例。調(diào)用request.user.is_authenticated()
是檢測當(dāng)前用戶是否認(rèn)證最好的方式。
編輯base.html
文件,修改ID為header
的<div>
,如下所示:
<div id="header">
<span class="logo">Bookmarks</span>
{% if request.user.is_authenticated %}
<ul class="menu">
<li {% if section == "dashboard" %}class="selected"{% endif %}>
<a href="{% url "dashboard" %}">My dashboard</a>
</li>
<li {% if section == "images" %}class="selected"{% endif %}>
<a href="#">Images</a>
</li>
<li {% if section == "people" %}class="selected"{% endif %}>
<a href="#">People</a>
</li>
</ul>
{% endif %}
<span class="user">
{% if request.user.is_authenticated %}
Hello {{ request.user.first_name }},
<a href="{% url "logout" %}">Logout</a>
{% else %}
<a href="{% url "login" %}">Log-in</a>
{% endif %}
</span>
</div>
正如你所看到的,我們只為認(rèn)證的用戶顯示網(wǎng)站的菜單。我們還檢查當(dāng)前的section,通過CSS為相應(yīng)的<li>
項(xiàng)添加selected
類屬性來高亮顯示菜單中的當(dāng)前section。我們還顯示用戶的姓,如果是認(rèn)證過的用戶,還顯示一個(gè)登出鏈接,否則顯示登錄鏈接。
現(xiàn)在,在瀏覽器中打開http://127.0.0.1:8000/account/login
。你會看到登錄頁面。輸入有效的用戶名和密碼,點(diǎn)擊Log-in
按鈕,你會看到這樣的頁面:
因?yàn)?code>My dashboard有selected
屬性,所以你會看到它是高亮顯示的。因?yàn)槭钦J(rèn)證過的用戶,所以用戶的姓顯示在頭部的右邊。點(diǎn)擊Logout
鏈接,你會看到下面的頁面:
在這個(gè)頁面中,用戶已經(jīng)登出,所以你不能再看到網(wǎng)站的菜單。現(xiàn)在頭部右邊顯示Log-in
鏈接。
如果你看到的是Django管理站點(diǎn)的登出頁面,而不是你自己的登出頁面,檢查項(xiàng)目的INSTALLED_APPS
設(shè)置,確保django.contrib.admin
在account
應(yīng)用之后。這兩個(gè)模板位于同樣的相對路徑中,Django目錄加載器會使用第一個(gè)。
4.2.4 修改密碼視圖
用戶登錄我們的網(wǎng)站后,我們需要用戶可以修改他們的密碼。我們通過集成Django認(rèn)證視圖來修改密碼。打開account
應(yīng)用的urls.py
文件,添加以下URL模式:
from django.contrib.auth.views import password_change
from django.contrib.auth.views import password_change_done
# change password urls
urlpatterns = [
url(r'^password-change/$', password_change, name='password_change'),
url(r'^password_change/done/$', password_change_done, name='password_change_done'),
]
password_change
視圖會處理修改密碼表單,password_change_done
會在用戶成功修改密碼后顯示一條成功消息。讓我們?yōu)槊總€(gè)視圖創(chuàng)建一個(gè)模板。
在account
應(yīng)用的templates/registration/
目錄中創(chuàng)建password_change_form.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Change you password{% endblock %}
{% block content %}
<h1>Change you password</h1>
<p>Use the form below to change your password.</p>
<form action="." method="post">
{{ form.as_p }}
<p><input type="submit" value="Change"></p>
{% csrf_token %}
</form>
{% endblock %}
該模板包括修改密碼的表單。在同一個(gè)目錄下創(chuàng)建password_change_done.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Password changed{% endblock %}
{% block content %}
<h1>Password changed</h1>
<p>Your password has been successfully changed.</p>
{% endblock %}
該模板只包括一條用戶成功修改密碼后顯示的成功消息。
在瀏覽器中打開http://127.0.0.1:8000/account/password-change/
。如果用戶沒有登錄,瀏覽器會重定向到登錄頁面。當(dāng)你認(rèn)證成功后,你會看到下面的修改密碼頁面:
在表單中填寫當(dāng)前密碼和新密碼,點(diǎn)擊Change
按鈕。你會看到以下成功頁面:
登出后,使用新密碼再次登錄,確定所有功能都能正常工作。
4.2.5 重置密碼視圖
在account
應(yīng)用的urls.py
文件中,為重置密碼添加以下URL模式:
from django.contrib.auth.views import password_reset
from django.contrib.auth.views import password_reset_done
from django.contrib.auth.views import password_rest_confirm
from django.contrib.auth.views import password_reset_complete
# restore password urls
url(r'^password-reset/$', password_reset, name='password_reset'),
url(r'^password-reset/done/$', password_reset_done, name='password_reset_done'),
url(r'^password-reset/confirm/(?P<uidb64>[-\w]+)/(?P<token>[-\w]+)/$', password_reset_confirm, name='password_reset_confirm'),
url(r'^password-reset/complete/$', password_reset_complete, name='password_reset_complete'),
在account
應(yīng)用的templates/registration/
目錄中創(chuàng)建password_reset_form.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Forgotten your password?</h1>
<p>Enter your e-mail address to obtain a new password.</p>
<form action="." method="post">
{{ form.as_p }}
<p><input type="submit" value="Send e-mail"></p>
{% csrf_token %}
</form>
{% endblock %}
在同一個(gè)目錄下創(chuàng)建password_reset_email.html
文件,添加以下代碼:
Someon asked for password reset for email {{ email }}. Fllow the link below:
{{ protocol }}://{{ domain }}/{% url "password_reset_form" uidb64=uid token=token %}
Your usernmae, in case you've forgotten: {{ user.get_username }}
這個(gè)模板用于渲染發(fā)送給用戶重置密碼的郵件。
在同一個(gè)目錄下創(chuàng)建password_reset_done.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Reset your password</h1>
<p>We've emailed you instructions for setting your password.</p>
<p>If you don't receive an email, please make sure you've entered the address you registered with.</p>
{% endblock %}
創(chuàng)建另一個(gè)模板文件password_reset_confirm.html
,添加以下代碼:
{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Reset your password</h1>
{% if validlink %}
<p>Please enter your new password twice:</p>
<form action="." method="post">
{{ formo.as_p }}
{% csrf_token %}
<p><input type="submit" value="Change my password" /></p>
</form>
{% else %}
<p>The password reset link was invalid, possible because it has already been used.
Please request a new password reset.</p>
{% endif %}
{% endblock %}
我們檢查提供的鏈接是否有效。Django重置頁面視圖設(shè)置該變量,并把它放在這個(gè)模板的上下文中。如果鏈接有效,我們顯示重置密碼表單。
創(chuàng)建另一個(gè)password_reset_complete.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Password reset{% endblock %}
{% block content %}
<h1>Password set</h1>
<p>Your password has been set. You can <a href="{% url "login" %}">log in now</a></p>
{% endblock %}
最后,編輯account
應(yīng)用的registration/login.html
模板,在<form>
元素后面添加以下代碼:
<p><a href="{% url "password_reset" %}">Forgotten your password?</a></p>
現(xiàn)在,在瀏覽器中打開htth://127.0.0.1:8000/account/login/
,點(diǎn)擊Forgotten your password?
鏈接,你會看到以下鏈接:
此時(shí),你需要在項(xiàng)目的settings.py
文件中添加SMTP
配置,讓Django可以發(fā)送郵件。我們已經(jīng)在第二章學(xué)習(xí)了如何添加郵件設(shè)置。但是在開發(fā)期間,你可以讓Django在標(biāo)準(zhǔn)輸出中寫郵件,代替通過SMTP服務(wù)發(fā)送郵件。Django提供了一個(gè)郵件后臺,可以把郵件輸出到控制臺。編輯項(xiàng)目的settings.py
文件,添加下面這一行代碼:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_BACKEND
設(shè)置指定用于發(fā)送郵件的類。
回到瀏覽器,輸入已有用戶的郵箱地址,點(diǎn)擊Send a e-mail
按鈕。你會看到以下頁面:
看一眼正在運(yùn)行開發(fā)服務(wù)器的控制臺,你會看到生成的郵件:
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Password reset on 127.0.0.1:8000
From: webmaster@localhost
To: lakerszhy@gmail.com
Date: Tue, 02 May 2017 03:50:20 -0000
Message-ID: <20170502035020.7440.93778@bogon>
Someon asked for password reset for email lakerszhy@gmail.com. Fllow the link below:
http://127.0.0.1:8000/account/password-reset/confirm/Mg/4lp-4b14906c833231658e9f/
Your usernmae, in case you've forgotten: antonio
郵件使用我們之間創(chuàng)建的password_reset_email.html
模板渲染。重置密碼的URL包括一個(gè)Django動(dòng)態(tài)生成的令牌。在瀏覽器中打開連接,會看到以下頁面:
設(shè)置新密碼的頁面對應(yīng)password_reset_confirm.html
模板。填寫新密碼并點(diǎn)擊Change my password
按鈕。Django會創(chuàng)建一個(gè)新的加密密碼,并保存到數(shù)據(jù)庫中。你會看到一個(gè)成功頁面:
現(xiàn)在你可以使用新密碼再次登錄。每個(gè)用于設(shè)置新密碼的令牌只能使用一次。如果你再次打開收到的鏈接,會看到一條令牌無效的消息。
你已經(jīng)在項(xiàng)目中集成了Django認(rèn)證框架的視圖。這些視圖適用于大部分場景。如果需要不同的行為,你可以創(chuàng)建自己的視圖。
4.3 用戶注冊和用戶資料
現(xiàn)在,已存在的用戶可以登錄,登出和修改密碼,如果用戶忘記密碼,可以重置密碼。現(xiàn)在,我們需要?jiǎng)?chuàng)建視圖,用于游客創(chuàng)建賬戶。
4.3.1 用戶注冊
讓我們創(chuàng)建一個(gè)簡單的視圖,允許用戶在我們的網(wǎng)站注冊。首先,我們必須創(chuàng)建一個(gè)表單,讓用戶輸入用戶名,姓名和密碼。編輯account
應(yīng)用中的forms.py
文件,添加以下代碼:
from django.contrib.auth.models import User
class UserRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'first_name', 'email')
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError("Passwords don't match.")
return cd['password2']
我們?yōu)?code>User模型創(chuàng)建了一個(gè)模型表單。在表單中,我們只包括了模型的username
,first_name
,email
字段。這些字段會根據(jù)相應(yīng)的模型字段驗(yàn)證。例如,如果用戶選擇了一個(gè)已存在的用戶名,會得到一個(gè)驗(yàn)證錯(cuò)誤。我們添加了兩個(gè)額外字段:password
和password2
,用來設(shè)置密碼和確認(rèn)密碼。我們定義了clean_password2()
方法,檢查兩次輸入的密碼是否一致,如果不一致,則讓表單無效。當(dāng)我們調(diào)用表單的is_valid()
方法驗(yàn)證時(shí),這個(gè)檢查會執(zhí)行。你可以為任何表單字段提供clean_<fieldname>()
方法,清理特定字段的值或拋出表單驗(yàn)證錯(cuò)誤。表單還包括一個(gè)通用的clean()
方法驗(yàn)證整個(gè)表單,驗(yàn)證相互依賴的字段時(shí)非常有用。
Django還在django.contrib.auth.forms
中提供了UserCreationForm
表單供你使用,這個(gè)表單跟我們剛創(chuàng)建的表單類似。
編輯account
應(yīng)用中的views.py
文件,添加以下代碼:
from .forms import LoginForm, UserRegistrationForm
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = user_form.save(commit=False)
# Set the chosen password
new_user.set_password(user_form.cleaned_data['password'])
# Save the User object
new_user.save()
return render(request, 'account/register_done.html', {'new_user': new_user})
else:
user_form = UserRegistrationForm()
return render(request, 'account/register.html', {'user_form': user_form})
這個(gè)創(chuàng)建用戶賬戶的視圖非常簡單。為了安全,我們使用User
模型的set_password()
方法處理加密保存,來代替保存用戶輸入的原始密碼。
現(xiàn)在編輯account
應(yīng)用的urls.py
文件,添加以下URL模式:
url(r'^register/$', views.register, name='register')
最后,我們在account/
模板目錄中創(chuàng)建register.html
文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Create an account{% endblock %}
{% block content %}
<h1>Create an account</h1>
<p>Please, sign up using the following form:</p>
<form action="." method="post">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Create my account"></p>
</form>
{% endblock %}
在同一個(gè)目錄中添加register_done.html
模板文件,添加以下代碼:
{% extends "base.html" %}
{% block title %}Welcome{% endblock %}
{% block content %}
<h1>Welcome {{ new_user.first_name }}!</h1>
<p>Your account has been successfully created. Now you can <a href="{% url "login" %}">log in</a>.</p>
{% endblock %}
現(xiàn)在,在瀏覽器中打開http://127.0.0.1:8000/account/register/
,你會看到剛創(chuàng)建的注冊頁面:
為新用戶填寫信息,點(diǎn)擊Create my account
按鈕。如果所有字段都有效,則會創(chuàng)建用戶,你會看到下面的成功消息:
點(diǎn)擊log in
鏈接,輸入你的用戶名和密碼驗(yàn)證能否訪問你的賬戶。
現(xiàn)在,你還可以在登錄模板中添加注冊鏈接。編輯registration/login.html
模板,把這行代碼:
<p>Please, user the following form to log-in</p>
替換為:
<p>Please, user the following form to log-in.
If you don't have an account <a href="{% url "register" %}">register here</a></p>
我們可以通過登錄頁面訪問注冊頁面了。
4.3.2 擴(kuò)展User模型
當(dāng)你必須處理用戶賬戶時(shí),你會發(fā)現(xiàn)Django認(rèn)證框架的User
模型適用于常見情況。但是User
模型有非常基礎(chǔ)的字段。你可能希望擴(kuò)展User
模型包含額外的數(shù)據(jù)。最好的方式是創(chuàng)建一個(gè)包括所有額外字段的個(gè)人資料模型,并且與Django的User
模型是一對一的關(guān)系。
編輯account
應(yīng)用的models.py
文件,添加以下代碼:
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/%Y/%m/%d', blank=True)
def __str__(self):
return 'Pofile for User {}'.format(self.user.username)
為了讓代碼保持通用性,請使用
get_user_model()
方法檢索用戶模型。同時(shí),定義模型和用戶模型之間的關(guān)系時(shí),使用AUTH_USER_MODEL
設(shè)置引用用戶模型,而不是直接引用該用戶模型。
一對一的user
字段允許我們用用戶關(guān)聯(lián)個(gè)人資料。photo
字段是一個(gè)ImageField
字段。你需要安裝PIL(Python Imaging Library)或Pillow(PIL的一個(gè)分支)Python包來管理圖片。在終端中執(zhí)行以下命令安裝Pillow:
pip install Pillow
為了在Django開發(fā)服務(wù)器中提供多媒體文件上傳功能,需要在項(xiàng)目的settings.py
文件中添加以下設(shè)置:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL
是用戶上傳的多媒體文件的基URL,MEDIA_ROOT
是多媒體文件的本地路徑。我們根據(jù)項(xiàng)目路徑動(dòng)態(tài)構(gòu)建該路徑,讓代碼更通用。
現(xiàn)在,編輯bookmarks
項(xiàng)目的主urls.py
文件,如下所示修改代碼:
from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
這樣,Django開發(fā)服務(wù)器將在開發(fā)過程中負(fù)責(zé)多媒體文件服務(wù)。
static()
幫助函數(shù)只適用于開發(fā)環(huán)境,不適合生產(chǎn)環(huán)境。永遠(yuǎn)不要在生產(chǎn)環(huán)境使用Django為靜態(tài)文件提供服務(wù)。
打開終端執(zhí)行以下命令,為新模型創(chuàng)建數(shù)據(jù)庫遷移:
python manage.py makemigrations
你會得到這樣的輸出:
Migrations for 'account':
account/migrations/0001_initial.py
- Create model Profile
接著使用以下命令同步數(shù)據(jù)庫:
python manage.py migrate
你會看到包括下面這一樣的輸出:
Applying account.0001_initial... OK
編輯account
應(yīng)用的admin.py
文件,在管理站點(diǎn)注冊Profile
模型,如下所示:
from .models import Profile
class ProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'date_of_birth', 'photo')
admin.site.register(Profile, ProfileAdmin)
使用python manage.py runserver
命令運(yùn)行開發(fā)服務(wù)器。現(xiàn)在,你會在項(xiàng)目的管理站點(diǎn)看到Profile
模型,如下圖所示:
現(xiàn)在,我們將讓用戶在網(wǎng)站上編輯個(gè)人資料。在account
應(yīng)用的forms.py
文件中添加以下模型表單:
from .models import Profile
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('date_of_birth', 'photo')
這些表單的作用是:
-
UserEditForm
:允許用戶編輯存在內(nèi)置的User
模型中的姓,名和郵箱。 -
ProfileEditForm
:允許用戶編輯存在自定義的Profile
模型中的額外數(shù)據(jù)。用戶可以編輯出生日期,并上傳一張圖片。
編輯account
應(yīng)用的views.py
文件,導(dǎo)入Profile
模型:
from .models import Profile
在register
視圖的new_user.save()
下面添加以下代碼:
# Create the user profile
profile = Profile.objects.create(user=new_user)
當(dāng)用戶在我們網(wǎng)站注冊時(shí),我們會創(chuàng)建一個(gè)空的個(gè)人資料關(guān)聯(lián)到用戶。你需要使用管理站點(diǎn)手動(dòng)為之前創(chuàng)建的用戶創(chuàng)建Profile
對象。
現(xiàn)在我們讓用戶可以編輯個(gè)人資料。添加以下代碼到同一個(gè)文件中:
from .forms import LoginForm, UserRegistrationForm, UserEditForm, ProfileEditForm
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user, data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request, 'account/edit.html', {'user_form': user_form, 'profile_form': profile_form})
我們使用了login_required
裝飾器,因?yàn)橛脩舯仨氄J(rèn)證后才能編輯個(gè)人資料。在這里,我們使用了兩個(gè)模型表單:UserEditForm
存儲內(nèi)置的User
模型數(shù)據(jù),ProfileEditForm
存儲額外的個(gè)人數(shù)據(jù)。我們檢查兩個(gè)表單的is_valid()
方法返回True來驗(yàn)證提交的數(shù)據(jù)。在這里,我們保持兩個(gè)表單,用來更新數(shù)據(jù)庫中相應(yīng)的對象。
在account
應(yīng)用的urls.py
文件中添加以下URL模式:
url(r'^edit/$', views.edit, name='edit')
最后,在templates/account/
目錄中,為該視圖創(chuàng)建edit.html
模板,添加以下代碼:
{% extends "base.html" %}
{% block title %}Edit your account{% endblock %}
{% block content %}
<h1>Edit your account</h1>
<p>You can edit your account using the following form:</p>
<form action="." method='post' enctype="multipart/form-data">
{{ user_form.as_p }}
{{ profile_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Save changes"></p>
</form>
{% endblock %}
我們在表單中包括了
enctype="multipart/form-data"
,來啟用文件上傳。我們使用一個(gè)HTML表單提交user_form
和profile_form
兩個(gè)表單。
注冊一個(gè)新用戶,并在瀏覽器中打開http://127.0.0.1:8000/account/edit/
,你會看到以下界面:
現(xiàn)在你可以編輯儀表盤頁面,來包括編輯個(gè)人資料和修改密碼的頁面鏈接。打開account/dashboard.html
模板,把這一行代碼:
<p>Welcome to your dashboard.</p>
替換為:
<p>
Welcome to your dashboard.
You can <a href="{% url "edit" %}">edit your profiles</a>
or <a href="{% url "password_change" %}">change your password</a>.
</p>
用戶現(xiàn)在可以通過儀表盤訪問編輯個(gè)人資料的表單。
4.3.2.1 使用自定義User模型
Django還提供了方式,可以用自定義模型代替整個(gè)User
模型。你的用戶類應(yīng)從Django的AbstractUser
類繼承,它作為一個(gè)抽象模型,提供了默認(rèn)用戶的完整實(shí)現(xiàn)。你可以在這里閱讀更多關(guān)于這個(gè)模型的信息。
使用自定義用戶模型會有更多的靈活性,但它也可能給一些需要與User
模型交互的可插拔應(yīng)用應(yīng)用的集成帶來一定的困難。
4.3.3 使用消息框架
處理用戶動(dòng)作時(shí),你可能想要通知用戶動(dòng)作的結(jié)果。Django內(nèi)置一個(gè)消息框架,允許你顯示一次性提示。該消息框架位于django.contrib.message
中,當(dāng)你用python manage.py startproject
創(chuàng)建新項(xiàng)目時(shí),它默認(rèn)包括在settings.py
的INSTALLED_APPS
列表中。你注意到,設(shè)置文件的MIDDLEWARE_CLASSES
設(shè)置列表中,包括一個(gè)名為django.contrib.message.middleware.MessageMiddleware
的中間件。該消息框架提供了一種簡單的方式來給用戶添加消息。消息存儲在數(shù)據(jù)庫中,并會在用戶下次請求時(shí)顯示。你可以通過導(dǎo)入消息模塊,使用簡單的快捷方式添加新消息,來在視圖中使用消息框架,如下所示:
from django.contrib import message
message.error(request, 'Something went wrong')
你可以使用add_message()
方法,或者以下任何一個(gè)快捷方法創(chuàng)建新消息:
-
success()
:動(dòng)作執(zhí)行成功后顯示成功消息 -
info()
:信息消息 -
waring()
:還沒有失敗,但很可能馬上失敗 -
error()
:一個(gè)不成功的操作,或某些事情失敗 -
debug()
:調(diào)試信息,會在生產(chǎn)環(huán)境移除或忽略
讓我們顯示消息給用戶。因?yàn)橄⒖蚣軐?xiàng)目來說是全局的,所以我們可以在基礎(chǔ)模板中顯示消息給用戶。打開base.html
模板,在id為header和content的<div>
元素之間添加以下代碼:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="{{ message.tags }}">
{{ message|safe }}
<a href="#" class="close">?</a>
</li>
{% endfor %}
</ul>
{% endif %}
消息框架包括一個(gè)上下文處理器(context processor),它會添加messages
變量到請求上下文中。因此,你可以在模板使用該變量顯示當(dāng)前消息。
現(xiàn)在,讓我們修改edit
視圖來使用消息框架。編輯account
應(yīng)用的views.py
文件,如下修改edit
視圖:
from django.contrib import messages
@login_required
def edit(request):
if request.method == 'POST':
# ...
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
# ...
當(dāng)用戶成功更新個(gè)人資料后,我們添加一條成功消息。如果任何一個(gè)表單無效,我們添加一條錯(cuò)誤消息。
在瀏覽器中打開http://127.0.0.1:8000/account/edit/
,并編輯你的個(gè)人資料。當(dāng)個(gè)人資料更新成功后,你會看到以下消息:
當(dāng)表單無效時(shí),你會看到以下消息:
4.4 創(chuàng)建自定義認(rèn)證后臺
Django允許你針對不同來源進(jìn)行身份驗(yàn)證。AUTHENTICATION_BACKENDS
設(shè)置包括了項(xiàng)目的認(rèn)證后臺列表。默認(rèn)情況下,該設(shè)置為:
('django.contrib.auth.backends.ModelBackend',)
默認(rèn)的ModelBackend
使用django.contrib.auth
的User
模型,驗(yàn)證數(shù)據(jù)庫中的用戶。這適用于大部分項(xiàng)目。但是你可以創(chuàng)建自定義的后臺,來驗(yàn)證其它來源的用戶,比如一個(gè)LDAP目錄或者其它系統(tǒng)。
你可以在這里閱讀更多關(guān)于自定義認(rèn)證的信息。
一旦你使用django.contrib.auth
中的authenticate()
函數(shù),Django會一個(gè)接一個(gè)嘗試AUTHENTICATION_BACKENDS
中定義的每一個(gè)后臺來驗(yàn)證用戶,直到其中一個(gè)驗(yàn)證成功。只有所有后臺都驗(yàn)證失敗,才不會在站點(diǎn)中驗(yàn)證通過。
Django提供了一種簡單的方式來定義自己的認(rèn)證后臺。一個(gè)認(rèn)證后臺是提供了以下兩個(gè)方法的類:
-
authenticate()
:接收用戶信息作為參數(shù),如果用戶認(rèn)證成功,則返回True,否則返回False。 -
get_user()
:接收用戶ID作為參數(shù),并返回一個(gè)User
對象。
創(chuàng)建一個(gè)自定義認(rèn)證后臺跟編寫一個(gè)實(shí)現(xiàn)這兩個(gè)方法的Python類一樣簡單。我們會創(chuàng)建一個(gè)認(rèn)證后臺,讓用戶使用郵箱地址代替用戶名驗(yàn)證。
在account
應(yīng)用目錄中創(chuàng)建一個(gè)authentication.py
文件,添加以下代碼:
from django.contrib.auth.models import User
class EmailAuthBackend:
"""
Authenticates using e-mail account.
"""
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
return None
except User.DoesNotExist:
retur None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
這是一個(gè)很簡單的認(rèn)證后臺。authenticate()
方法接收username
和password
作為可選參數(shù)。我們可以使用不同的參數(shù),但我們使用username
和password
確保后臺可以立即在認(rèn)證框架中工作。上面的代碼完成以下工作:
-
authenticate()
:我們嘗試使用給定的郵箱地址檢索用戶,并用User
模型內(nèi)置的check_password()
方法檢查密碼。該方法會處理密碼哈希化,并比較給定的密碼和數(shù)據(jù)庫中存儲的密碼。 -
get_user()
:我們通過user_id
參數(shù)獲得一個(gè)用戶。在用戶會話期間,Django使用認(rèn)證用戶的后臺來檢索User
對象。
編輯項(xiàng)目的settings.py
,添加以下設(shè)置:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthBackend',
)
我們保留了默認(rèn)的ModelBackend
,使用用戶名和密碼認(rèn)證,并包括了自己的基于郵箱地址的認(rèn)證后臺。現(xiàn)在,在瀏覽器中打開http://127.0.0.1/8000/account/login/
。記住,Django會試圖使用每一個(gè)后臺驗(yàn)證用戶,所以你現(xiàn)在可以使用用戶名或郵箱賬號登錄。
AUTHENTICATION_ BACKENDS
設(shè)置中列出的后端順序很重要。如果同樣的信息對于多個(gè)后臺都有效,Django會在第一個(gè)成功驗(yàn)證用戶的后臺停止。
4.5 為網(wǎng)站添加社交認(rèn)證
你可能還想為網(wǎng)站添加社交認(rèn)證,比如使用Facebook,Twitter或Google服務(wù)認(rèn)證。Python-socail-auth
是一個(gè)Python模塊,可以簡化添加社交認(rèn)證過程。通過這個(gè)模塊,你可以讓用戶使用其他服務(wù)的賬戶登錄你的網(wǎng)站。
譯者注:從2016年12月3日開始,這個(gè)模塊遷移到了Python Social Auth。原書的內(nèi)容已經(jīng)過時(shí),所以就不翻譯了。
4.6 總結(jié)
在本章中,你學(xué)習(xí)了如何在網(wǎng)站中構(gòu)建認(rèn)證系統(tǒng)和創(chuàng)建自定義用戶資料。你還在網(wǎng)站中添加了社交認(rèn)證。
下一章中,你會學(xué)習(xí)如何創(chuàng)建一個(gè)圖片書簽系統(tǒng),生成圖片的縮略圖,以及創(chuàng)建AJAX視圖。