轉自:http://www.lxweimin.com/p/06670f9aa439
第四章
創建一個社交網站
在上一章中,你學習了如何創建站點地圖(sitemaps)和feeds,你還為你的blog應用創建了一個搜索引擎。在本章中,你將開發一個社交應用。你會為用戶創建一些功能,例如:登錄,登出,編輯,以及重置他們的密碼。你會學習如何為你的用戶創建一個定制的profile,你還會為你的站點添加社交認證。
本章將會覆蓋以下幾點:
- 使用認證(authentication)框架
- 創建用戶注冊視圖(views)
- 通過一個定制的profile模型(model)擴展User模型(model)
- 使用python-social-auth添加社交認證
讓我們開始創建我們的新項目吧。
創建一個社交網站項目
我們要創建一個社交應用允許用戶分享他們在網上找到的圖片。我們需要為這個項目構建以下元素:
- 一個用來給用戶注冊,登錄,編輯他們的profile,以及改變或重置密碼的認證(authentication)系統
- 一個允許用戶用來關注其他人的關注系統(這里原文是follow,‘跟隨’,感覺用‘關注’更加適合點)
- 為用戶從其他任何網站分享過來的圖片進行展示和打上書簽
- 每個用戶都有一個活動流允許用戶看到他們關注的人上傳的內容
本章主要講述第一點。
開始你的社交網站項目
運行以下命令來創建一個新項目:
django-admin statproject bookmarks
在創建好一個初始的項目結構以后,使用以下命令進入你的項目目錄并且創建一個新的應用命名為account:
cd bookmarks/django-admin startapp account
請記住在你的項目中激活一個新應用需要在settings.py文件中的INSTALLED_APPS設置中添加它。將新應用的名字添加在INSTALLED_APPS列中的所有已安裝應用的最前面,如下所示:
INSTALLED_APPS = (
'account',
# ...
)
運行下一條命令為INSTALLED_APPS中默認包含的應用模型(models)同步到數據庫中:
python manage.py migrate
我們將要使用認證(authentication)框架來構建一個認證系統到我們的項目中。
使用Django認證(authentication)框架
Django擁有一個內置的認證(authentication)框架用來操作用戶認證(authentication),會話(sessions),權限(permissions)以及用戶組。這個認證(authentication)系統包含了一些普通用戶的操作視圖(views),例如:登錄,登出,修改密碼以及重置密碼。
這個認證(authentication)框架位于django.contrib.auth,被其他Django的contrib包調用。請記住你使用過這個認證(authentication)框架在第一章 創建一個Blog應用中用來為你的blog應用創建了一個超級用戶來使用管理站點。
當你使用startproject命令創建一個新的Django項目,認證(authentication)框架已經在你的/項目設置中默認包含。它是由django.contrib.auth應用和你的項目設置中的MIDDLEWARE_CLASSES中的兩個中間件類組成,如下:
- AuthenticationMiddlwware:使用會話(sessions)將用戶和請求(requests)進行關聯
- SessionMiddleware:通過請求(requests)操作當前會話(sessions)
中間件就是一個在請求和響應階段帶有全局執行方法的類。你會在本書中的很多場景中使用到中間件。你將會學習如何創建一個定制的中間件在第十三章 Going Live(譯者注:啥時候能翻譯到啊)。
這個認證(authentication)系統還包含了以下模型(models):
- User:一個用戶模型(model)包含基礎字段;這個模型(model)的主要字段有:
username
,password
,first_name
,last_name
,is_active
。
- Group:一個組模型(model)用來分類用戶
- Permission:執行特定操作的標識
這個框架還包含默認的認證(authentication)視圖(views)和表單(forms),我們之后會用到。
創建一個log-in視圖(view)
我們將要開始使用Django認證(authentication)框架來允許用戶登錄我們的網站。我們的視圖(view)需要執行以下操作來登錄用戶:
1、通過提交的表單(form)獲取username和password
2、通過存儲在數據庫中的數據對用戶進行認證
3、檢查用戶是否可用
4、登錄用戶到網站中并且開始一個認證(authentication)會話(session)
首先,我們要創建一個登錄表單(form)。在你的account應用目錄下創建一個新的forms.py文件,添加如下代碼:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
這個表單(form)被用來通過數據庫認證用戶。請注意,我們使用PsswordInput控件來渲染HTMLinput
元素,包含type="password
屬性。編輯你的account應用中的views.py文件,添加如下代碼:
from django.http import HttpResponse
from django.shortcuts import render
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})
以上就是我們在視圖(view)中所作的基本登錄操作:當user_login被一個GET請求(request)調用,我們實例化一個新的登錄表單(form)通過form = LoginForm()
在模板(template)中展示它。當用戶通過POST方法提交表單(form),我們執行以下操作:
1、使用提交的數據實例化表單(form)通過使用
form = LoginForm(request.POST)
2、檢查這個表單是否有效。如果無效,我們在模板(template)中展示表單錯誤信息(舉個例如,比如用戶沒有填寫其中一個字段就進行提交)
3、如果提交的數據是有效的,我們通過數據庫對這個用戶進行認證(authentication)通過使用authenticate()
方法。這個方法帶入一個username和一個password并且返回一個用戶對象如果這個用戶成功的進行了認證,或者是None。如果用戶沒有被認證通過,我們返回一個HttpResponse展示一條消息。
4、如果這個用戶認證(authentication)成功,我們使用is_active
屬性來檢查用戶是否可用。這是一個Django的User模型(model)屬性。如果這個用戶不可用,我們返回一個HttpResponse展示信息。
5、如果用戶可用,我們登錄這個用戶到網站中。我們通過調用login()
方法集合用戶到會話(session)中然后返回一條成功消息。
- 請注意authentication和login中的不同點:authenticate()檢查用戶認證信息然后返回一個用戶對象如果用戶是正確的;login()集合用戶到當前的會話(session)中。
現在,你需要為這個視圖(view)創建一個URL模式。在你的account應用目錄下創建一個新的urls.py文件,添加如下代碼:
from django.conf.urls import url
from . import views
urlpatterns = [
# post views
url(r'^login/$', views.user_login, name='login'),
]
編輯位于你的bookmarks項目目錄下的urls.py文件,將account應用下的URL模式包含進去:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^account/',include('account.urls')),
]
這個登錄視圖(view)現在已經可以通過URL進行訪問。現在是時候為這個視圖(view)創建一個模板。
因為之前你沒有這個項目的任何模板,你可以開始創建一個主模板(template)可以被登錄模板(template)繼承使用。創建以下文件和結構在account應用目錄中:
templates/account/base.html, templates/account/login.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>
以上將是這個網站的基礎模板(template)。就像我們在上一章項目中做過的一樣,我們在這個住模板(template)中包含了CSS樣式。你可以在本章的示例代碼中找到這些靜態文件。復制示例代碼中的account應用下的static/目錄到你的項目中的相同位置,這樣你就可以使用這些靜態文件了。
基礎模板(template)定義了一個title和一個content區塊可以被繼承的子模板(template)填充內容。
讓我們為我們的登錄表單(form)創建模板(template)。打開account/login.html模板(template)添加如下代碼:
{% extends "account/base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Log-in</h1>
<p>Please, use 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 %}
這個模板(template)包含了視圖(view)中實例化的表單(form)。因為我們的表單(form)將會通過POST方式進行提交,所以我們包含了{% csrf_token %}
模板(template)標簽(tag)用來通過CSRF保護。你已經學習過CSRF保護在第二章 使用高級特性擴展你的博客應用。
目前還沒有用戶在你的數據庫中。你首先需要創建一個超級用戶用來登錄管理站點來管理其他的用戶。打開命令行執行python manage.py createsuperuser
。填寫username,e-mail以及password。之后通過命令python manage.py runserver
運行開發環境,然后在你的瀏覽器中打開 http://127.0.0.1:8000/admin/ 。使用你剛才創建的username和passowrd來進入管理站點。你會看到Django管理站點包含Django認證(authentication)框架中的User和Group模型(models)。如下所示:
使用管理站點創建一個新的用戶然后打開 http://127.0.0.1:8000/account/login/ 。你會看到被渲染過的模板(template),包含一個登錄表單(form):
# 因為沒有css,所以頁面是原始樣式
加個css樣式
https://pan.baidu.com/s/1bpaKg83 密碼: tzic ,里面示例代碼有base.css
加好后訪問
現在,只填寫一個字段保持另外一個字段為空進行表單(from)提交。在這例子中,你會看到這個表單(form)是無效的并且顯示了一個錯誤信息:
如果你輸入了一個不存在的用戶或者一個錯誤的密碼,你會得到一個Invalid login信息。
如果你輸入了有效的認證信息,你會得到一個Authenticated successfully消息。
使用Django認證(authentication)視圖(views)
Django包含了一些表單(forms)和視圖(views)在認證(authentication)框架中讓你可以立刻(straightaway)使用。你之前創建的登錄視圖(view)是一個非常的練習用來理解Django中的用戶認證(authentication)過程。無論如何,你可以使用默認的Django認證(authentication)視圖(views)在大部分的例子中。
Django提供以下視圖(views)來處理認證(authentication):
- login:操作表單(form)中的登錄然后登錄一個用戶
- logout:登出一個用戶
- logout_then_login:登出一個用戶然后重定向這個用戶到登錄頁面
Django提供以下視圖(views)來操作密碼修改:
- password_change:操作一個表單(form)來修改用戶密碼
- password_change_done:當用戶成功修改他的密碼后提供一個成功提示頁面
Django還包含了以下視圖(views)允許用戶重置他們的密碼:
- password_reset:允許用戶重置他的密碼。它會生成一條帶有一個token的一次性使用鏈接然后發送到用戶的郵箱中。
- password_reset_done:告知用戶已經發送了一封可以用來重置密碼的郵件到他的郵箱中。
- password_reset_complete:當用戶重置完成他的密碼后提供一個成功提示頁面。
以上的視圖(views)可以幫你節省很多時間當你創建一個帶有用戶賬號的網站。這些視圖(views)使用的默認值你可以進行覆蓋,例如需要渲染的模板位置或者視圖(view)需要使用到的表單(form)。
你可以通過訪問 https://docs.djangoproject.com/en/1.8/topics/auth/default/#module-django.contrib.auth.views 獲取更多內置的認證(authentication)視圖(views)信息。
登錄和登出視圖(views)
編輯你的account應用下的urls.py文件,如下所示:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^login/$', 'django.contrib.auth.views.login', name='login'),
url(r'^logout/$', 'django.contrib.auth.views.logout', name='logout'),
url(r'^logout-then-login/$', 'django.contrib.auth.views.logout_then_login', name='logout_then_login'),
]
這種寫法會報錯,view must be a callable or a list/tuple in the case of include()
解決:
from django.conf.urls import url
from .views import dashboard
from django.contrib.auth import views
urlpatterns = [
# post views
url(r'^login/$', views.login, name='login'),
url(r'^logout/$', views.logout, name='logout'),
url(r'^logout-then-login/$', views.logout_then_login, name='logout_then_login'),
]
我們將之前創建的user_login視圖(view)URL模式進行注釋,然后使用Django認證(authentication)框架提供的login視圖(view)。
在你的account應用中的template目錄下創建一個新的目錄命名為registration。這個路徑是Django認證(authentication)視圖(view)期望你的認證(authentication)模塊(template)默認的存放路徑。在這個新目錄中創建一個新的文件,命名為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, use 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 %}
這個登錄模板(template)和我們之前創建的基本類似。Django默認使用位于django.contrib.auth.forms中的AuthenticationForm。這個表單(form)會嘗試對用戶進行認證如果登錄不成功就會拋出一個驗證錯誤。在這個例子中,我們可以在模板(template)中使用{% if form.errors %}來找到錯誤如果用戶提供了錯誤的認證信息。
請注意,我們添加了一個隱藏的HTML<input>元素來提交叫做next的變量值。這個變量是登錄視圖(view)的首個設置當你在請求(request)中傳遞一個next參數(舉個例子:http://127.0.0.1:8000/account/login/?next=/account/)。
next參數必須是一個URL。當這個參數被給予的時候,Django登錄視圖(view)將會在用戶登錄完成后重定向到給予的URL。
現在,在registrtion模板(template)目錄下創建一個logged_out.html模板(template)添加如下代碼:
{% 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 %}
這個模板(template)Django會在用戶登出的時候進行展示。
在添加了URL模式以及登錄和登出視圖(view)的模板之后,你的網站已經準備好讓用戶使用Django認證(authentication)視圖進行登錄。
請注意,在我們的地址配置中包含的logtou_then_login視圖(view)不需要任何模板(template),因為它執行了一個重定向到登錄視圖(view)。
現在,我們要創建一個新的視圖(view)來顯示一個dashboard給用戶當他或她登錄他們的賬號。打開你的account應用中的views.py文件,添加以下代碼:
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, 'account/dashboard.html', {'section': 'dashboard'})
我們使用認證authentication
框架的login_required裝飾器decorator
裝飾我們的視圖view
。login_required裝飾器decorator
會檢查當前用戶是否通過認證,如果用戶通過認證,它會執行裝飾的視圖view
,如果用戶沒有通過認證,它會把用戶重定向到帶有一個名為next的GET參數的登錄URL,該GET參數保存的變量為用戶當前嘗試訪問的頁面URL。通過這些動作,登錄視圖view
會將登錄成功的用戶重定向到用戶登錄之前嘗試訪問過的URL。請記住我們在登錄模板template
中的登錄表單form
中添加的隱藏<input>就是為了這個目的。
我們還定義了一個section變量。我們會使用該變量來跟蹤用戶在站點中正在查看的頁面。多個視圖(views)可能會對應相同的section。這是一個簡單的方法用來定義每個視圖(view)對應的section。
現在,你需要創建一個給dashboard視圖(view)使用的模板(template)。在templates/account/目錄下創建一個新文件命名為dashboard.html。添加如下代碼:
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
{% endblock %}
之后,為這個視圖(view)在account應用中的urls.py文件中添加如下URL模式:
url(r'^$', views.dashboard, name='dashboard'),
編輯你的項目的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')
這些設置的意義:
- LOGIN_REDIRECT_URL:告訴Django用戶登錄成功后如果contrib.auth.views.login視圖(view)沒有獲取到next參數將會默認重定向到哪個URL。
- LOGIN_URL:重定向用戶登錄的URL(例如:使用login_required裝飾器(decorator))。
- LOGOUT_URL:重定向用戶登出的URL。
我們使用reverse_laze()來動態構建URL通過它們的名字。reverse_laze()方法reverses URLs就像reverse()所做的一樣,但是你可以使用它當你需要reverse URLs在你項目的URL配置讀取之前。
讓我們總結下目前為止我們都做了哪些工作:
你在項目中添加了Django內置的認證(authentication)登錄和登出視圖(views)。
你為每一個視圖(view)創建了定制的模板(templates),并且定義了一個簡單的視圖(view)讓用戶登錄后進行重定向。
最后,你配置了你的Django設置使用默認的URLs。
現在,我們要給我們的主模板(template)添加登錄和登出鏈接將所有的一切都連接起來。
為了做到這點,我們必須確定無論用戶是已登錄狀態還是沒有登錄的時候,都會顯示適當的鏈接。通過認證(authentication)中間件當前的用戶被集合在HTTP請求(request)對象中。你可以訪問用戶信息通過使用request.user
。你會防線一個用戶對象在請求(request)中,即使這個用戶并沒有認證通過。一個非認證的用戶在請求(request)被設置成一個AnonymousUser的實例。一個最好的方法來檢查當前的用戶是否通過認證是通過調用request.user.is_authenticated()
。
編輯你的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>
{% 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>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
就像你所看到的,我們只給通過認證(authentication)的用戶顯示站點菜單。我們還檢查當前的section來給對應的<li>
組件添加一個selected的class屬性來使當前section在菜單中進行高亮顯示通過使用CSS。我們還顯示用戶的第一個名字和一個登出的鏈接如果用戶已經通過認證(authentication),否則,就是一個登出鏈接。
現在,在瀏覽器中打開 http://127.0.0.1:8000/account/login/ 。你會看到登錄頁面。輸入可用的用戶名和密碼然后點擊Log-in按鈕。你會看到如下圖所示:
你能看到My Dashboard section 通過CSS的作用高亮顯示因為它擁有一個selected class。因為當前用戶已經通過了認證(authentication)所有用戶的第一個名字在右上角進行了顯示。點擊Logout鏈接。你會看到如下圖所示:
在這個頁面中,你能看到用戶已經登出,然后,你無法看到當前網站的任何菜單。在右上角現在顯示的是Log-in鏈接。
如果你在你的登出頁面中看到了Django管理站點的登出頁面,檢查項目settings.py中的INSTALLED_APPS,確保django.contrib.admin在account應用的后面。每個模板(template)被定位在同樣的相對路徑時,Django模板(template)讀取器將會使用它找到的第一個應用中的模板(templates)。
修改密碼視圖(views)
我們還需要我們的用戶在登錄成功后可以進行修改密碼。我們要集成Django認證(authentication)視圖(views)來修改密碼。打開account應用中的urls.py文件,添加如下URL模式:
url(r'^password-change/$', views.password_change, name='password_change'),
url(r'^password-change/done/$', views.password_change_done, name='password_change_done'),
password_change視圖(view)將會操作表單(form)進行修改密碼,password_change_done將會顯示一條成功信息當用戶成功的修改他的密碼。讓我們為每個視圖(view)創建一個模板(template)。
在你的account應用templates/registration/目錄下添加一個新的文件命名為password_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 %}
這個模板(template)包含了修改密碼的表單(form)。現在,在相同的目錄下創建另一個文件,命名為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 %}
這個模板(template)只包含顯示一條成功的信息 當用戶成功的修改他們的密碼。
在base.html的 {% if request.user.is_authenticated %}
下面加一行
<a href="{% url "password_change" %}"> 修改密碼 </a>
刷新頁面即可看到,如果你的用戶沒有登錄,瀏覽器會重定向你到登錄頁面。在你成功認證(authentication)登錄后,你會看到如下
點擊修改密碼頁面,按要求改完密碼后,會看到如下頁面:
登出再使用新的密碼進行登錄來驗證每件事是否如預期一樣工作。
重置密碼視圖(views)
在account應用urls.py文件中為密碼重置添加如下URL模式:
# restore password urls
url(r'^password-reset/$', 'django.contrib.auth.views.password_reset', name='password_reset'),
url(r'^password-reset/done/$', 'django.contrib.auth.views.password_reset_done', name='password_reset_done'),
url(r'^password-reset/confirm/(?P<uidb64>[-\w]+)/(?P<token>[-\w]+)/$',
'django.contrib.auth.views.password_reset_confirm', name='password_reset_confirm'),
url(r'^password-reset/complete/$', 'django.contrib.auth.views.password_reset_complete',
name='password_reset_complete'),
在你的account應用templates/registration/目錄下添加一個新的文件命名為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 %}
現在,在相同的目錄下添加另一個文件命名為password_reset_email.html,為它添加如下代碼:
Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %}
Your username, in case you've forgotten: {{ user.get_username }}
這個模板(template)會被用來渲染發送給用戶的重置密碼郵件。
在相同目錄下添加另一個文件命名為*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 %}
再創建另一個模板(template)命名為passowrd_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">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Change my password" /></p>
</form>
{% else %}
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
{% endif %}
{% endblock %}
在以上模板中,如果重置鏈接是有效的我們將會進行檢查。Django重置密碼視圖(view)會設置這個變量然后將它帶入這個模板(template)的上下文環境中。如果重置鏈接有效,我們展示用戶密碼重置表單(form)。
創建另一個模板(template)命名為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應用中的/registration/login.html模板(template),添加如下代碼在<form>
元素之后:
<p><a href="{% url "password_reset" %}">Forgotten your password?</a></p>
現在,在瀏覽器中打開 http://127.0.0.1:8000/account/login/ 然后點擊Forgotten your password?鏈接。你會看到如下圖所示頁面:
在這部分,你需要在你項目中的settings.py中添加一個SMTP配置,這樣Django才能發送e-mails。我們已經學習過如何添加e-mail配置在第二章 使用高級特性來優化你的blog。當然,在開發期間,我們可以配置Django在標準輸出中輸出e-mail內容來代替通過SMTP服務發送郵件。Django提供一個e-mail后端來輸出e-mail內容到控制器中。編輯項目中settings.py文件,添加如下代碼:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_BACKEND設置這個類用來發送e-mails。
回到你的瀏覽器中,填寫一個存在用戶的e-mail地址,然后點擊Send e-mail按鈕。你會看到如下圖所示頁面:
當你運行開發服務的時候看眼控制臺輸出。你會看到如下所示生成的e-mail: