Django Tutorial Part 7: Sessions framework

翻譯不完整。 請幫助我們翻譯這篇文章!

本教程擴展了我們的LocalLibrary 網站,為主頁添加了一個基於會話的訪問計數器。這是一個相對簡單的例子,但它確實顯示了,如何使用會話框架,為匿名用戶提供持久的行為。

Prerequisites: 完成所有先前的教程主题,包括Django教程第6部分:通用列表和详细视图
Objective: 了解如何使用会话.

概覽

我们在之前的教程中创建的LocalLibrary网站允许用户浏览目录中的书籍和作者. 虽然内容是从数据库动态生成的,但每个用户在使用该网站时基本上都可以访问相同的页面和信息类型.

在一个``真实''的库中,您可能希望根据用户以前对网站的使用,首选项等为单个用户提供定制的体验. 例如,您可以隐藏用户下次访问时已经确认的警告消息. 网站,或存储并尊重他们的偏好(例如,他们希望在每个页面上显示的搜索结果的数量).

會話框架允許您實現這種行為,從而允許您基於每個站點訪問者存儲和檢索任意數據。

What are sessions?

Web瀏覽器和服務器之間的所有通信都是通過HTTP協議進行的,該協議是無狀態的。該協議是無狀態的事實意味著客戶端和服務器之間的消息是完全相互獨立的-沒有基於先前消息的“序列”或行為的概念。因此,如果您想擁有一個跟踪與客戶之間正在進行的關係的站點,則需要自己實施。

會話是Django(以及大多數Internet)使用的機制,用於跟踪站點與特定瀏覽器之間的“狀態”。會話允許您在每個瀏覽器中存儲任意數據,並且只要瀏覽器連接,該數據就可用於站點。然後,與會話相關聯的單個數據項被一個``鍵''引用,該鍵既用於存儲又用於檢索數據。

Django使用包含特殊会话ID的cookie来标识每个浏览器及其与站点的关联会话. 默认情况下,实际会话数据默认存储在站点数据库中(这比将数据存储在cookie中更安全,因为cookie在cookie中更容易受到恶意用户的攻击). 您可以将Django配置为将会话数据存储在其他位置(缓存,文件或是"安全" Cookie),但是默认位置是一个很好且相对安全的选择.

Enabling sessions

當我們創建框架網站時(在教程2中),將自動啟用會話。

在項目文件的INSTALLED_APPS 和MIDDLEWARE 部分中進行配置(locallibrary/locallibrary/settings.py),如下所示:

INSTALLED_APPS = [
    ...
    'django.contrib.sessions',
    ....

MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    ....

Using sessions

您可以从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到期日期以及从数据存储中清除过期的会话. 您可以在如How to use sessions找到完整的API(Django文档).

Saving session data

默认情况下,当会话已被修改(分配)或删除时,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

注意:您可以更改行為,以便站點可以通過在您的項目設置(locallibrary/locallibrary/settings.py)中添加SESSION_SAVE_EVERY_REQUEST = True 來更新每個請求的數據庫/發送cookie。

Simple example — getting visit counts

作為一個簡單的真實示例,我們將更新我們的庫以告知當前用戶他們訪問LocalLibrary主頁的次數。

打開/ /locallibrary/catalog/views.py,然後進行以下粗體顯示的更改。

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)
    request.session['num_visits'] = num_visits + 1

    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(例如,請參閱How to use sessions)或設計我們的UI,以便無論是否支持cookie都無關緊要。

將以下區塊底部看到的行添加到``動態內容''部分底部的主HTML模板(/locallibrary/catalog/templates/index.html)中以顯示上下文變量:

<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 }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p>

保存更改,然后重新启动测试服务器. 每次刷新页面时,数字都会更新.

總結

現在,您知道使用會話來改善與匿名用戶的交互是多麼容易。

在接下來的文章中,我們將說明身份驗證和授權(權限)框架,並向您展示如何支持用戶帳戶。

See also

In this module