codecamp

Django Tutorial Part 7: Sessions framework

先决条件: 完成之前的所有教学主题,包括 Django教程第6部分:通用列表和详细信息视图
目的: 了解如何使用会话。

概述

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

在"真实"库中,您可能希望根据用户以前对网站,偏好设置等的使用情况为个别用户提供自定义体验。例如,您可以隐藏用户以前在下次访问时所确认的警告消息 站点或存储并尊重他们的偏好(例如他们希望在每一页上显示的搜索结果的数量)。

会话框架允许您实现此类行为,允许您在每个站点访问者的基础上存储和检索任意数据。

什么是会话?

网络浏览器和服务器之间的所有通信都是通过HTTP协议进行的,这是无状态 协议是无状态的意味着客户端和服务器之间的消息彼此完全独立 - 没有基于先前消息的"序列"或行为的概念。 因此,如果你想有一个网站跟踪与客户端的持续关系,你需要自己实现。

会话是Django(和大多数Internet)用于跟踪站点和特定浏览器之间的"状态"的机制。 会话允许您为每个浏览器存储任意数据,并在浏览器连接时将此数据提供给网站。 与会话相关联的各个数据项然后由"密钥"引用,"密钥"用于存储和检索数据。

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

启用会话

当我们创建骨架网站(在教程2中)时,会话自动启用。

配置在项目文件( locallibrary / 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到期日期,以及清除数据存储中的过期会话。 您可以在如何使用会话中找到完整的API Django docs)。

保存会话数据

默认情况下,Django仅保存到会话数据库,并在会话已修改(分配)或已删除时将会话cookie发送到客户端。 如果你使用它的会话密钥更新一些数据,如上一节所示,那么你不需要担心这个! 例如:

# This is detected as an update to the session, so session data is saved.
request.session['my_car'] = 'mini'

如果您要更新会话数据中的某些信息,Django将无法识别您对会话所做的更改并保存了数据(例如,如果您要更改" 轮子"数据在" my_car "数据内,如下所示)。 在这种情况下,您需要将会话显式标记为已修改。

# 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

注意:您可以更改行为,以便网站可以通过向您的项目设置中添加 SESSION_SAVE_EVERY_REQUEST = True 来更新每个请求的数据库/发送Cookie( locallibrary / locallibrary /settings.py )。

简单的例子 - 获取访问计数

作为一个简单的现实示例,我们将更新库以告知当前用户他们访问了 LocalLibrary 主页的次数。

打开 /localibrary/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
    
    # Render the HTML template index.html with the data in the context variable.
    return render(
        request,
        'index.html',
        context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors,
            'num_visits':num_visits}, # num_visits appended
    )

这里我们首先获取\'num_visits\'会话密钥的值,如果之前未设置,则将值设置为0。 每次收到请求时,我们都会增加该值并将其存回会话中(下次用户访问页面时)。 然后将 num_visits 变量传递给我们的上下文变量中的模板。

注意:我们还可以测试浏览器是否支持Cookie(请参阅 http / 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>

保存更改并重新启动测试服务器。 每次刷新页面时,数字都应该更新。

    概要

    您现在知道使用会话改善与匿名用户的互动是多么容易。

    您现在知道使用会话改善与匿名用户的互动是多么容易。...

    也可以看看

    Django Tutorial Part 6: Generic list and detail views
    Django Tutorial Part 8: User authentication and permissions
    温馨提示
    下载编程狮App,免费阅读超1000+编程语言教程
    取消
    确定
    目录
    CSS

    关闭

    MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }