Django 教程 第 7 部分:會話框架
本教程擴充套件了我們的 LocalLibrary 網站,在首頁添加了一個基於會話的訪問計數器。這是一個相對簡單的示例,但它確實展示瞭如何在自己的網站中使用會話框架為匿名使用者提供持久行為。
| 先決條件 | 完成所有之前的教程主題,包括 Django 教程 第 6 部分:通用列表和詳細資訊檢視 |
|---|---|
| 目標 | 瞭解如何使用會話。 |
概述
我們在之前的教程中建立的 LocalLibrary 網站允許使用者瀏覽目錄中的書籍和作者。雖然內容是從資料庫動態生成的,但每個使用者在使用網站時基本上都可以訪問相同的頁面和資訊型別。
在“真正的”圖書館中,您可能希望根據使用者之前對網站的使用情況、偏好等為每個使用者提供個性化的體驗。例如,您可以隱藏使用者之前已確認的警告訊息,或者儲存並尊重他們的偏好(例如,他們希望在每個頁面上顯示的搜尋結果數量)。
會話框架允許您實現這種行為,允許您基於每個網站訪問者儲存和檢索任意資料。
什麼是會話?
Web 瀏覽器和伺服器之間所有通訊都透過 HTTP 進行,它是無狀態的。協議無狀態的事實意味著客戶端和伺服器之間的訊息彼此完全獨立——沒有“序列”的概念,也沒有基於先前訊息的行為。因此,如果您希望擁有一個跟蹤與客戶端持續關係的網站,則需要自己實現。
會話是 Django(以及大多數網際網路)用於跟蹤網站和特定瀏覽器之間“狀態”的機制。會話允許您為每個瀏覽器儲存任意資料,並在瀏覽器連線到網站時使這些資料可用。然後,與會話關聯的單個數據項透過“鍵”進行引用,該鍵用於儲存和檢索資料。
Django 使用包含特殊會話 ID 的 cookie 來識別每個瀏覽器及其與網站關聯的會話。實際的會話資料預設儲存在網站資料庫中(這比將資料儲存在 cookie 中更安全,因為 cookie 更容易受到惡意使用者的攻擊)。您可以配置 Django 將會話資料儲存在其他位置(快取、檔案、“安全” cookie),但預設位置是一個良好且相對安全的選項。
啟用會話
當我們 建立網站框架(在教程 2 中)時,會話已自動啟用。
配置設定在專案檔案(django-locallibrary-tutorial/locallibrary/settings.py)的INSTALLED_APPS 和MIDDLEWARE 部分中,如下所示
INSTALLED_APPS = [
# …
'django.contrib.sessions',
# …
MIDDLEWARE = [
# …
'django.contrib.sessions.middleware.SessionMiddleware',
# …
使用會話
您可以從request 引數(作為檢視的第一個引數傳入的HttpRequest)中的檢視訪問session 屬性。此會話屬性表示與當前使用者(或更準確地說,與當前瀏覽器的連線,由該網站的瀏覽器 cookie 中的會話 ID 標識)。
session 屬性是一個類似字典的物件,您可以在檢視中對其進行任意次數的讀取和寫入,並根據需要對其進行修改。您可以執行所有正常的字典操作,包括清除所有資料、測試鍵是否存在、迴圈遍歷資料等。但是,大多數情況下,您只會使用標準的“字典”API 來獲取和設定值。
下面的程式碼片段顯示瞭如何使用與當前會話(瀏覽器)關聯的鍵“my_car”獲取、設定和刪除一些資料。
注意:Django 的一大優點是您無需在檢視中考慮將會話繫結到當前請求的機制。如果我們在檢視中使用下面的片段,我們會知道有關my_car的資訊僅與傳送當前請求的瀏覽器相關聯。
# Get a session value by its key (e.g. 'my_car'), raising a KeyError if the key is not present
my_car = request.session['my_car']
# Get a session value, setting a default if it is not present ('mini')
my_car = request.session.get('my_car', 'mini')
# Set a session value
request.session['my_car'] = 'mini'
# Delete a session value
del request.session['my_car']
API 還提供了一些其他方法,這些方法主要用於管理關聯的會話 cookie。例如,有一些方法可以測試客戶端瀏覽器是否支援 cookie,設定和檢查 cookie 過期日期,以及清除資料儲存中已過期的會話。您可以在 如何使用會話(Django 文件)中瞭解有關完整 API 的資訊。
儲存會話資料
預設情況下,只有在會話被修改(賦值)或刪除時,Django 才會儲存到會話資料庫並將會話 cookie 傳送到客戶端。如果您使用其會話鍵更新某些資料(如上一節所示),則無需擔心!例如
# This is detected as an update to the session, so session data is saved.
request.session['my_car'] = 'mini'
如果您正在更新會話資料內部的一些資訊,那麼 Django 將無法識別您已對會話進行了更改並儲存資料(例如,如果您要更改“my_car”資料內部的“wheels”資料,如下所示)。在這種情況下,您需要顯式標記會話已被修改。
# Session object not directly modified, only data within the session. Session changes not saved!
request.session['my_car']['wheels'] = 'alloy'
# Set session as modified to force data updates/cookie to be saved.
request.session.modified = True
注意:您可以更改行為,以便網站在每次請求時更新資料庫/傳送 cookie,方法是在專案設定(django-locallibrary-tutorial/locallibrary/settings.py)中新增SESSION_SAVE_EVERY_REQUEST = True。
簡單示例 - 獲取訪問次數
作為一個簡單的現實世界示例,我們將更新我們的庫以告知當前使用者他們訪問了多少次LocalLibrary 首頁。
開啟/django-locallibrary-tutorial/catalog/views.py,並將包含num_visits 的行新增到index() 中(如下所示)。
def index(request):
# …
num_authors = Author.objects.count() # The 'all()' is implied by default.
# Number of visits to this view, as counted in the session variable.
num_visits = request.session.get('num_visits', 0)
num_visits += 1
request.session['num_visits'] = num_visits
context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
'num_visits': num_visits,
}
# Render the HTML template index.html with the data in the context variable.
return render(request, 'index.html', context=context)
在這裡,我們首先獲取'num_visits' 會話鍵的值,如果之前未設定該值,則將其設定為 0。每次收到請求時,我們都會遞增該值並將其儲存回會話中(以便使用者下次訪問頁面時使用)。然後,num_visits 變數在我們的上下文變數中傳遞給模板。
注意:我們還可以在這裡測試瀏覽器是否支援 cookie(有關示例,請參閱 如何使用會話)或設計我們的 UI,以便無論是否支援 cookie 都無關緊要。
將以下程式碼塊底部所示的行新增到您的主 HTML 模板(/django-locallibrary-tutorial/catalog/templates/index.html)中“動態內容”部分的底部,以顯示num_visits 上下文變數。
<h2>Dynamic content</h2>
<p>The library has the following record counts:</p>
<ul>
<li><strong>Books:</strong> {{ num_books }}</li>
<li><strong>Copies:</strong> {{ num_instances }}</li>
<li><strong>Copies available:</strong> {{ num_instances_available }}</li>
<li><strong>Authors:</strong> {{ num_authors }}</li>
</ul>
<p>
You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.
</p>
請注意,我們使用 Django 內建的模板標籤 pluralize 在頁面被訪問多次時新增“s”。
儲存更改並重新啟動測試伺服器。每次重新整理頁面時,數字都應該更新。
總結
現在您知道使用會話改善與匿名使用者互動是多麼容易了。
在我們的下一篇文章中,我們將解釋身份驗證和授權(許可權)框架,並向您展示如何支援使用者帳戶。
另請參閱
- 如何使用會話(Django 文件)