{"title":"如何使用会话","version":"6.0","locale":"zh-hans","docname":"topics/http/sessions","url":"/zh-hans/6.0/topics/http/sessions/","canonical":"https://djangodocs.dev/zh-hans/6.0/topics/http/sessions/","summary":"Django 提供了对匿名会话的全面支持。会话框架允许你在每个站点访问者的基础上存储和检索任意数据。它将数据存储在服务器端并抽象了 cookie 的发送和接收。Cookies 包含会话 ID - 而不是数据本身（除非你使用 基于 cookie 的后端 ）。 启用会话 Link to this heading # 会话是通过一段…","html":"<span id=\"how-to-use-sessions\"></span><h1>如何使用会话<a class=\"heading-anchor\" href=\"#module-django.contrib.sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django 提供了对匿名会话的全面支持。会话框架允许你在每个站点访问者的基础上存储和检索任意数据。它将数据存储在服务器端并抽象了 cookie 的发送和接收。Cookies 包含会话 ID - 而不是数据本身（除非你使用 <a class=\"reference internal\" href=\"#cookie-session-backend\"><span class=\"std std-ref\">基于 cookie 的后端</span></a>）。</p>\n<section id=\"enabling-sessions\">\n<h2>启用会话<a class=\"heading-anchor\" href=\"#enabling-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>会话是通过一段 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/middleware/\"><span class=\"doc\">中间件</span></a> 实现的。</p>\n<p>要启用会话功能，请执行以下操作：</p>\n<ul class=\"simple\">\n<li><p>编辑 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 设置，并确保其中包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.contrib.sessions.middleware.SessionMiddleware'</span></code>。由 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-admin</span> <span class=\"pre\">startproject</span></code> 创建的默认 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> 已经激活了 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionMiddleware</span></code>。</p></li>\n</ul>\n<p>如果你不想使用会话，你也可以从 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-MIDDLEWARE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">MIDDLEWARE</span></code></a> 中删除 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionMiddleware</span></code> 行，并从 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 中删除 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.contrib.sessions'</span></code>。这将节省一些小额开销。</p>\n</section>\n<section id=\"configuring-the-session-engine\">\n<span id=\"configuring-sessions\"></span><h2>配置会话引擎<a class=\"heading-anchor\" href=\"#configuring-the-session-engine\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>默认情况下，Django 将会话存储在数据库中（使用模型 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions.models.Session</span></code>）。尽管这很方便，但在某些设置中，将会话数据存储在其他地方可能更快，因此可以配置 Django 将会话数据存储在文件系统或缓存中。</p>\n<section id=\"using-database-backed-sessions\">\n<h3>使用基于数据库的会话<a class=\"heading-anchor\" href=\"#using-database-backed-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果要使用基于数据库的会话，需要将 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.contrib.sessions'</span></code> 添加到你的 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 设置中。</p>\n<p>一旦配置完成，运行 <code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code> 来安装存储会话数据的单个数据库表。</p>\n</section>\n<section id=\"using-cached-sessions\">\n<span id=\"cached-sessions-backend\"></span><h3>使用缓存会话<a class=\"heading-anchor\" href=\"#using-cached-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>为了获得更好的性能，你可能想要使用基于缓存的会话后端。</p>\n<p>要使用 Django 的缓存系统存储会话数据，首先需要确保你已经配置了缓存；请查看 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/cache/\"><span class=\"doc\">缓存文档</span></a> 获取详细信息。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>只有当你使用 Memcached 或 Redis 缓存后端时，才应该使用基于缓存的会话。本地内存缓存后端不会保留数据足够长的时间，因此不是一个好选择，直接使用文件或数据库会话可能会更快，而不是通过文件或数据库缓存后端发送所有数据。此外，本地内存缓存后端不是多进程安全的，因此在生产环境中可能不是一个好选择。</p>\n</aside>\n<p>如果在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CACHES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CACHES</span></code></a> 中定义了多个缓存，Django 将使用默认缓存。要使用另一个缓存，将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_CACHE_ALIAS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_CACHE_ALIAS</span></code></a> 设置为该缓存的名称。</p>\n<p>一旦配置了缓存，你需要在数据库支持的缓存和非持久性缓存之间进行选择。</p>\n<p>缓存数据库后端（<code class=\"docutils literal notranslate\"><span class=\"pre\">cached_db</span></code>）使用直写式缓存 —— 会话写入按顺序同时应用于数据库和缓存。如果写入缓存失败，异常将通过 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/logging/#django-contrib-sessions-logger\"><span class=\"std std-ref\">sessions logger</span></a> 进行处理和记录，以避免导致其他成功的写入操作失败。</p>\n<p>会话读取使用缓存，如果数据已从缓存中逐出，则使用数据库。要使用此后端，请将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.contrib.sessions.backends.cached_db&quot;</span></code>，并按照 <a class=\"reference internal\" href=\"#using-database-backed-sessions\">使用数据库支持的会话</a> 的配置说明进行操作。</p>\n<p>缓存后端（<code class=\"docutils literal notranslate\"><span class=\"pre\">cache</span></code>）只在缓存中存储会话数据。这更快，因为它避免了数据库持久性，但你需要考虑当缓存数据被逐出时会发生什么情况。逐出可能发生在缓存填满或缓存服务器重新启动时，这将意味着会话数据丢失，包括用户的注销状态。要使用此后端，请将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.contrib.sessions.backends.cache&quot;</span></code>。</p>\n<p>缓存后端可以通过使用具有适当配置的持久缓存（例如 Redis）来变成持久性的。但除非你的缓存明确配置为具有足够的持久性，否则选择缓存数据库后端是更安全的选择。这可以避免由于生产中不可靠的数据存储引起的边缘情况。</p>\n</section>\n<section id=\"using-file-based-sessions\">\n<h3>使用基于文件的会话<a class=\"heading-anchor\" href=\"#using-file-based-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要使用基于文件的会话，请将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.contrib.sessions.backends.file&quot;</span></code>。</p>\n<p>你可能还想设置 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_FILE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_FILE_PATH</span></code></a> 配置（默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">tempfile.gettempdir()</span></code> 的输出，很可能是 <code class=\"docutils literal notranslate\"><span class=\"pre\">/tmp</span></code>）来控制 Django 存储会话文件的位置。请确保你的 Web 服务器具有读写此位置的权限。</p>\n</section>\n<section id=\"using-cookie-based-sessions\">\n<span id=\"cookie-session-backend\"></span><h3>使用基于 cookie 的会话<a class=\"heading-anchor\" href=\"#using-cookie-based-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要使用基于 cookie 的会话，请将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;django.contrib.sessions.backends.signed_cookies&quot;</span></code>。会话数据将使用 Django 的 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/signing/\"><span class=\"doc\">加密签名</span></a> 工具和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SECRET_KEY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SECRET_KEY</span></code></a> 设置存储。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>建议将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_HTTPONLY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_HTTPONLY</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，以防止 JavaScript 访问存储的数据。</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p><strong>会话数据被签名但未加密</strong></p>\n<p>在使用基于 cookie 的后端时，会话数据可以被客户端读取。</p>\n<p>使用 MAC（消息认证码）用于保护数据免受客户端的更改，以便在被篡改时会话数据将被作废。如果存储 cookie 的客户端（例如你用户的浏览器）无法存储全部会话 cookie 并丢弃数据，会发生相同的作废。尽管 Django 对数据进行了压缩，但仍然完全有可能超过每个 cookie 的 <span class=\"target\" id=\"index-2\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc2965.html#section-5.3\"><strong>常见限制 4096 字节</strong></a>。</p>\n<p><strong>不保证新鲜度</strong></p>\n<p>还要注意，虽然 MAC 可以保证数据的真实性（即它是由你的站点生成的，而不是其他人生成的），以及数据的完整性（即它都在那里且正确），但它不能保证新鲜度，也就是不能保证你被发送回客户端的是最后发送给客户端的内容。这意味着对于一些使用会话数据的情况，基于 cookie 的后端可能会使你容易受到 <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Replay_attack\">重放攻击</a> 的威胁。与其他会话后端不同，这些后端会保留每个会话的服务器端记录，并在用户注销时使其失效，基于 cookie 的会话在用户注销时不会失效。因此，如果攻击者窃取了用户的 cookie，即使用户注销，他们仍然可以使用该 cookie 以该用户的身份登录。只有当 cookie 的寿命超过 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a> 时，它们才会被检测为 '过时'。</p>\n<p><strong>性能</strong></p>\n<p>最后，cookie 的大小可能会影响你的网站的速度。</p>\n</aside>\n</section>\n</section>\n<section id=\"using-sessions-in-views\">\n<h2>在视图中使用会话<a class=\"heading-anchor\" href=\"#using-sessions-in-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>当激活了 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionMiddleware</span></code> 时，每个 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/request-response/#django.http.HttpRequest\" title=\"django.http.HttpRequest\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">HttpRequest</span></code></a> 对象 -- 作为任何 Django 视图函数的第一个参数 -- 都将具有一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">session</span></code> 属性，它是一个类似于字典的对象。</p>\n<p>你可以在视图的任何时候读取并写入 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code>。你可以多次编辑它。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">backends.base.</span></span><span class=\"sig-name descname\"><span class=\"pre\">SessionBase</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>这是所有会话对象的基类。它具有以下标准的字典方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.__getitem__\">\n<span class=\"sig-name descname\"><span class=\"pre\">__getitem__</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.__getitem__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">fav_color</span> <span class=\"pre\">=</span> <span class=\"pre\">request.session['fav_color']</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.__setitem__\">\n<span class=\"sig-name descname\"><span class=\"pre\">__setitem__</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.__setitem__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">request.session['fav_color']</span> <span class=\"pre\">=</span> <span class=\"pre\">'blue'</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.__delitem__\">\n<span class=\"sig-name descname\"><span class=\"pre\">__delitem__</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.__delitem__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">del</span> <span class=\"pre\">request.session['fav_color']</span></code> 。如果给定的 <code class=\"docutils literal notranslate\"><span class=\"pre\">key</span></code> 不在会话里，会引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">KeyError</span></code> 。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.__contains__\">\n<span class=\"sig-name descname\"><span class=\"pre\">__contains__</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.__contains__\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">'fav_color'</span> <span class=\"pre\">in</span> <span class=\"pre\">request.session</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.get\">\n<span class=\"sig-name descname\"><span class=\"pre\">get</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">default</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.get\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aget\">\n<span class=\"sig-name descname\"><span class=\"pre\">aget</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">default</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aget\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>: <code class=\"docutils literal notranslate\"><span class=\"pre\">aget()</span></code></p>\n<p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">fav_color</span> <span class=\"pre\">=</span> <span class=\"pre\">request.session.get('fav_color',</span> <span class=\"pre\">'red')</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aset\">\n<span class=\"sig-name descname\"><span class=\"pre\">aset</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aset\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>示例：<code class=\"docutils literal notranslate\"><span class=\"pre\">await</span> <span class=\"pre\">request.session.aset('fav_color',</span> <span class=\"pre\">'red')</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.update\">\n<span class=\"sig-name descname\"><span class=\"pre\">update</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dict</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.update\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aupdate\">\n<span class=\"sig-name descname\"><span class=\"pre\">aupdate</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dict</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aupdate\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>: <code class=\"docutils literal notranslate\"><span class=\"pre\">aupdate()</span></code></p>\n<p>示例：<code class=\"docutils literal notranslate\"><span class=\"pre\">request.session.update({'fav_color':</span> <span class=\"pre\">'red'})</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.pop\">\n<span class=\"sig-name descname\"><span class=\"pre\">pop</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">default</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">__not_given</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.pop\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.apop\">\n<span class=\"sig-name descname\"><span class=\"pre\">apop</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">default</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">__not_given</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.apop\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">apop()</span></code></p>\n<p>比如：<code class=\"docutils literal notranslate\"><span class=\"pre\">fav_color</span> <span class=\"pre\">=</span> <span class=\"pre\">request.session.pop('fav_color',</span> <span class=\"pre\">'blue')</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.keys\">\n<span class=\"sig-name descname\"><span class=\"pre\">keys</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.keys\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.akeys\">\n<span class=\"sig-name descname\"><span class=\"pre\">akeys</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.akeys\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">akeys()</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.values\">\n<span class=\"sig-name descname\"><span class=\"pre\">values</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.values\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.avalues\">\n<span class=\"sig-name descname\"><span class=\"pre\">avalues</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.avalues\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">avalues()</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.has_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_key</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.has_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.ahas_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">ahas_key</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">key</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.ahas_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">ahas_key()</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.items\">\n<span class=\"sig-name descname\"><span class=\"pre\">items</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.items\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aitems\">\n<span class=\"sig-name descname\"><span class=\"pre\">aitems</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aitems\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aitems()</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.setdefault\">\n<span class=\"sig-name descname\"><span class=\"pre\">setdefault</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.setdefault\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.asetdefault\">\n<span class=\"sig-name descname\"><span class=\"pre\">asetdefault</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.asetdefault\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">asetdefault()</span></code></p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.clear\">\n<span class=\"sig-name descname\"><span class=\"pre\">clear</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.clear\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>它也有以下方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.flush\">\n<span class=\"sig-name descname\"><span class=\"pre\">flush</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.flush\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aflush\">\n<span class=\"sig-name descname\"><span class=\"pre\">aflush</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aflush\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aflush()</span></code></p>\n<p>Deletes the current session data from the session and deletes the session\ncookie. This is used if you want to ensure that the previous session data\ncan't be accessed again from the user's browser (for example, the\n<a class=\"reference internal\" href=\"/zh-hans/6.0/topics/auth/default/#django.contrib.auth.logout\" title=\"django.contrib.auth.logout\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.logout()</span></code></a> function calls it).</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.is_empty\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_empty</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.is_empty\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Returns <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if the session does not have a key and is empty.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.set_test_cookie\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_test_cookie</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.set_test_cookie\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aset_test_cookie\">\n<span class=\"sig-name descname\"><span class=\"pre\">aset_test_cookie</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aset_test_cookie\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aset_test_cookie()</span></code></p>\n<p>设置一个测试 cookie 来确定用户的浏览器是否支持 cookie。由于 cookie 的工作方式，你将无法在用户的下一个页面请求之前进行测试。有关更多信息，请参阅下面的 <a class=\"reference internal\" href=\"#setting-test-cookies\">设置测试 cookie</a>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.test_cookie_worked\">\n<span class=\"sig-name descname\"><span class=\"pre\">test_cookie_worked</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.test_cookie_worked\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.atest_cookie_worked\">\n<span class=\"sig-name descname\"><span class=\"pre\">atest_cookie_worked</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.atest_cookie_worked\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">atest_cookie_worked()</span></code></p>\n<p>根据用户的浏览器是否接受测试 cookie，返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>。由于 cookie 的工作方式，你必须在之前的单独页面请求中调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">set_test_cookie()</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">aset_test_cookie()</span></code>。有关更多信息，请参阅下面的 <a class=\"reference internal\" href=\"#setting-test-cookies\">设置测试 cookie</a>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.delete_test_cookie\">\n<span class=\"sig-name descname\"><span class=\"pre\">delete_test_cookie</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.delete_test_cookie\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.adelete_test_cookie\">\n<span class=\"sig-name descname\"><span class=\"pre\">adelete_test_cookie</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.adelete_test_cookie\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">adelete_test_cookie()</span></code></p>\n<p>删除测试 cookie。使用它来清理。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.get_session_cookie_age\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_session_cookie_age</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.get_session_cookie_age\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a> 设置的值。这可以在自定义会话后端中进行覆盖。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.set_expiry\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_expiry</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.set_expiry\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aset_expiry\">\n<span class=\"sig-name descname\"><span class=\"pre\">aset_expiry</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">value</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aset_expiry\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aset_expiry()</span></code></p>\n<p>设置会话的过期时间。你可以传递多种不同的值：</p>\n<ul class=\"simple\">\n<li><p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 是一个整数，会话将在多少秒的不活动后过期。例如，调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session.set_expiry(300)</span></code> 会使会话在5分钟后过期。</p></li>\n<li><p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 是一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">timedelta</span></code> 对象，会话将在特定的日期/时间过期。</p></li>\n<li><p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>，用户的会话 cookie 将在用户关闭 Web 浏览器时过期。</p></li>\n<li><p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">value</span></code> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，会话将恢复使用全局会话过期策略。</p></li>\n</ul>\n<p>读取会话不被视为用于过期目的的活动。会话过期是根据会话上次被 <em>修改</em> 的时间计算的。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.get_expiry_age\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_expiry_age</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.get_expiry_age\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aget_expiry_age\">\n<span class=\"sig-name descname\"><span class=\"pre\">aget_expiry_age</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aget_expiry_age\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aget_expiry_age()</span></code></p>\n<p>返回会话过期前剩余的秒数。对于没有自定义过期时间的会话（或设置为在关闭浏览器时过期的会话），这将等于 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a>。</p>\n<p>此函数接受两个可选的关键字参数：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">modification</span></code>：会话的最后修改时间，作为一个 <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.datetime\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">datetime</span></code></a> 对象。默认为当前时间。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">expiry</span></code>：会话的过期信息，可以是 <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#datetime.datetime\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">datetime</span></code></a> 对象、<code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">int`（以秒为单位）或</span> <span class=\"pre\">``None`</span></code>。默认为 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.set_expiry\" title=\"django.contrib.sessions.backends.base.SessionBase.set_expiry\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_expiry()</span></code></a>/<a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.aset_expiry\" title=\"django.contrib.sessions.backends.base.SessionBase.aset_expiry\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">aset_expiry()</span></code></a> 存储在会话中的值（如果有），否则为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p></li>\n</ul>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>这个方法用于会话后端在保存会话时确定会话过期时间的秒数。它实际上并不打算在那种上下文之外使用。</p>\n<p>特别是，尽管在你拥有正确的 <code class=\"docutils literal notranslate\"><span class=\"pre\">modification</span></code> 值 <strong>且</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">expiry</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> 对象的情况下可以 <strong>可能</strong> 确定会话的剩余寿命，但在你有 <code class=\"docutils literal notranslate\"><span class=\"pre\">modification</span></code> 值的情况下，手动计算到期时间更加直接：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">expires_at</span> <span class=\"o\">=</span> <span class=\"n\">modification</span> <span class=\"o\">+</span> <span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">seconds</span><span class=\"o\">=</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">SESSION_COOKIE_AGE</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.get_expiry_date\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_expiry_date</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.get_expiry_date\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aget_expiry_date\">\n<span class=\"sig-name descname\"><span class=\"pre\">aget_expiry_date</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aget_expiry_date\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aget_expiry_date()</span></code></p>\n<p>返回会话将过期的日期。对于没有自定义过期时间的会话（或设置为在关闭浏览器时过期的会话），这将等于从现在开始 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a> 秒后的日期。</p>\n<p>此函数接受与 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.get_expiry_age\" title=\"django.contrib.sessions.backends.base.SessionBase.get_expiry_age\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_expiry_age()</span></code></a> 相同的关键字参数，并适用类似的用法注意事项。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.get_expire_at_browser_close\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_expire_at_browser_close</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.get_expire_at_browser_close\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aget_expire_at_browser_close\">\n<span class=\"sig-name descname\"><span class=\"pre\">aget_expire_at_browser_close</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aget_expire_at_browser_close\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aget_expire_at_browser_close()</span></code></p>\n<p>根据用户的会话 cookie 是否在用户关闭 Web 浏览器时过期，返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.clear_expired\">\n<span class=\"sig-name descname\"><span class=\"pre\">clear_expired</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.clear_expired\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.aclear_expired\">\n<span class=\"sig-name descname\"><span class=\"pre\">aclear_expired</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.aclear_expired\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aclear_expired()</span></code></p>\n<p>从会话存储中删除已过期的会话。这个类方法由 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-clearsessions\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">clearsessions</span></code></a> 调用。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.cycle_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">cycle_key</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.cycle_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.base.SessionBase.acycle_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">acycle_key</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.base.SessionBase.acycle_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">acycle_key()</span></code></p>\n<p>Creates a new session key while retaining the current session data.\n<a class=\"reference internal\" href=\"/zh-hans/6.0/topics/auth/default/#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.login()</span></code></a> calls this method to mitigate against\nsession fixation.</p>\n</dd></dl>\n\n</dd></dl>\n\n<section id=\"session-serialization\">\n<span id=\"id1\"></span><h3>会话序列化<a class=\"heading-anchor\" href=\"#session-serialization\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>默认情况下，Django使用 JSON 对会话数据进行序列化。你可以使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_SERIALIZER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_SERIALIZER</span></code></a> 设置来自定义会话序列化格式。尽管在 <a class=\"reference internal\" href=\"#custom-serializers\"><span class=\"std std-ref\">编写你自己的序列化器</span></a> 中描述了一些注意事项，但我们强烈建议 <em>特别是如果你使用的是基于 cookie 的后端</em>，坚持使用 JSON 序列化。</p>\n<p>例如，如果你使用 <a class=\"reference external\" href=\"https://docs.python.org/3/library/pickle.html#module-pickle\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">pickle</span></code></a> 来序列化会话数据，以下是一个攻击场景。如果你使用的是 <a class=\"reference internal\" href=\"#cookie-session-backend\"><span class=\"std std-ref\">签名 cookie 会话后端</span></a> 并且 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SECRET_KEY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SECRET_KEY</span></code></a> （或 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SECRET_KEY_FALLBACKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SECRET_KEY_FALLBACKS</span></code></a> 的任何密钥）被攻击者知道（Django 本身没有内在的漏洞会导致其泄露），攻击者可以在他们的会话中插入一个字符串，当反序列化时，它在服务器上执行任意代码。这种技巧很简单，而且在互联网上很容易找到。尽管 cookie 会话存储对 cookie 中存储的数据进行了签名以防止篡改，但 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SECRET_KEY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SECRET_KEY</span></code></a> 泄漏会立即升级为远程代码执行漏洞。</p>\n<section id=\"bundled-serializers\">\n<h4>捆绑的序列化器<a class=\"heading-anchor\" href=\"#bundled-serializers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.serializers.JSONSerializer\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">serializers.</span></span><span class=\"sig-name descname\"><span class=\"pre\">JSONSerializer</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.serializers.JSONSerializer\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个包装了 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/signing/#module-django.core.signing\" title=\"django.core.signing: Django's signing framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.core.signing</span></code></a> 中的 JSON 序列化器的包装器。只能序列化基本数据类型。</p>\n<p>此外，由于 JSON 只支持字符串键，因此请注意在 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 中使用非字符串键不会按预期工作：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># initial assignment</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;bar&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># subsequent requests following serialization &amp; deserialization</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># of session data</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span>  <span class=\"c1\"># KeyError</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;0&quot;</span><span class=\"p\">]</span>\n<span class=\"go\">&#39;bar&#39;</span>\n</code></pre></div>\n<p>类似地，不能编码为 JSON 的数据，例如不能编码为 UTF-8 的字节，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">'\\xd9'</span></code> （会引发 <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#UnicodeDecodeError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">UnicodeDecodeError</span></code></a>），也无法存储。</p>\n<p>请参阅 <a class=\"reference internal\" href=\"#custom-serializers\"><span class=\"std std-ref\">编写你自己的序列化器</span></a> 部分以获取关于 JSON 序列化的限制的更多详细信息。</p>\n</dd></dl>\n\n</section>\n<section id=\"write-your-own-serializer\">\n<span id=\"custom-serializers\"></span><h4>编写你自己的序列化器<a class=\"heading-anchor\" href=\"#write-your-own-serializer\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>请注意， <a class=\"reference internal\" href=\"#django.contrib.sessions.serializers.JSONSerializer\" title=\"django.contrib.sessions.serializers.JSONSerializer\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">JSONSerializer</span></code></a> 不能处理任意的 Python 数据类型。通常情况下，方便和安全之间存在权衡。如果你希望在 JSON 支持的会话中存储更高级的数据类型，包括 <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">Decimal</span></code>，你需要编写一个自定义的序列化器（或在存储到 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 之前将这些值转换为可 JSON 序列化的对象）。尽管序列化这些值通常很简单（<a class=\"reference internal\" href=\"/zh-hans/6.0/topics/serialization/#django.core.serializers.json.DjangoJSONEncoder\" title=\"django.core.serializers.json.DjangoJSONEncoder\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DjangoJSONEncoder</span></code></a> 可能会有所帮助），但编写一个可以可靠地获取与放入相同的东西的解码器更加脆弱。例如，你可能会冒险返回一个实际上是一个字符串的 <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code>，只是碰巧与为 <code class=\"docutils literal notranslate\"><span class=\"pre\">datetime</span></code> 选择的相同格式。</p>\n<p>你的序列化器类必须实现两个方法，<code class=\"docutils literal notranslate\"><span class=\"pre\">dumps(self,</span> <span class=\"pre\">obj)</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">loads(self,</span> <span class=\"pre\">data)</span></code>，分别用于序列化和反序列化会话数据的字典。</p>\n</section>\n</section>\n<section id=\"session-object-guidelines\">\n<h3>会话对象指南<a class=\"heading-anchor\" href=\"#session-object-guidelines\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<ul class=\"simple\">\n<li><p>在 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 上使用普通的 Python 字符串作为字典键。这更像是一种约定而不是硬性规则。</p></li>\n<li><p>以下划线开头的会话字典键被保留供 Django 内部使用。</p></li>\n<li><p>不要用新对象覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code>，也不要访问或设置它的属性。像使用 Python 字典一样使用它。</p></li>\n</ul>\n</section>\n<section id=\"examples\">\n<h3>示例<a class=\"heading-anchor\" href=\"#examples\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>这个简单的视图在用户发布评论后将一个变量 <code class=\"docutils literal notranslate\"><span class=\"pre\">has_commented</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。它不允许用户发布多次评论：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post_comment</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">new_comment</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;has_commented&quot;</span><span class=\"p\">,</span> <span class=\"kc\">False</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;ve already commented.&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">comments</span><span class=\"o\">.</span><span class=\"n\">Comment</span><span class=\"p\">(</span><span class=\"n\">comment</span><span class=\"o\">=</span><span class=\"n\">new_comment</span><span class=\"p\">)</span>\n    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n    <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;has_commented&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;Thanks for your comment!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这个简单的视图登录了站点的一个“成员”：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">login</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">m</span> <span class=\"o\">=</span> <span class=\"n\">Member</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">POST</span><span class=\"p\">[</span><span class=\"s2\">&quot;username&quot;</span><span class=\"p\">])</span>\n    <span class=\"k\">if</span> <span class=\"n\">m</span><span class=\"o\">.</span><span class=\"n\">check_password</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">POST</span><span class=\"p\">[</span><span class=\"s2\">&quot;password&quot;</span><span class=\"p\">]):</span>\n        <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;member_id&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">m</span><span class=\"o\">.</span><span class=\"n\">id</span>\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re logged in.&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;Your username and password didn&#39;t match.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>...而这一个则根据上面的 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 方法将成员注销：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">logout</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">try</span><span class=\"p\">:</span>\n        <span class=\"k\">del</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;member_id&quot;</span><span class=\"p\">]</span>\n    <span class=\"k\">except</span> <span class=\"ne\">KeyError</span><span class=\"p\">:</span>\n        <span class=\"k\">pass</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re logged out.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>标准的 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/auth/default/#django.contrib.auth.logout\" title=\"django.contrib.auth.logout\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.logout()</span></code></a> 函数实际上做了更多的工作，以防止意外的数据泄露。它调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 的 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.flush\" title=\"django.contrib.sessions.backends.base.SessionBase.flush\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">flush()</span></code></a> 方法。我们在这个示例中只是演示如何使用会话对象，而不是完整的 <code class=\"docutils literal notranslate\"><span class=\"pre\">logout()</span></code> 实现。</p>\n</section>\n</section>\n<section id=\"setting-test-cookies\">\n<h2>设置测试 cookie<a class=\"heading-anchor\" href=\"#setting-test-cookies\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>作为一种便利，Django 提供了一种测试用户浏览器是否接受 cookie 的方法。在视图中调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 的 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.set_test_cookie\" title=\"django.contrib.sessions.backends.base.SessionBase.set_test_cookie\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_test_cookie()</span></code></a> 方法，并在后续的视图中调用 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.test_cookie_worked\" title=\"django.contrib.sessions.backends.base.SessionBase.test_cookie_worked\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">test_cookie_worked()</span></code></a> -- 不要在同一个视图调用中执行。</p>\n<p>这种 <code class=\"docutils literal notranslate\"><span class=\"pre\">set_test_cookie()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">test_cookie_worked()</span></code> 之间的分离方式是由于 cookie 的工作方式所必需的。当你设置一个 cookie 时，你实际上无法知道浏览器是否接受了它，直到浏览器的下一个请求。</p>\n<p>It's good practice to use\n<a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.delete_test_cookie\" title=\"django.contrib.sessions.backends.base.SessionBase.delete_test_cookie\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">delete_test_cookie()</span></code></a> to clean up after\nyourself. Do this after you've verified that the test cookie worked.</p>\n<p>这里是一个典型的用法示例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">login</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">method</span> <span class=\"o\">==</span> <span class=\"s2\">&quot;POST&quot;</span><span class=\"p\">:</span>\n        <span class=\"k\">if</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">test_cookie_worked</span><span class=\"p\">():</span>\n            <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">delete_test_cookie</span><span class=\"p\">()</span>\n            <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;You&#39;re logged in.&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;Please enable cookies and try again.&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">set_test_cookie</span><span class=\"p\">()</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s2\">&quot;foo/login_form.html&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"using-sessions-out-of-views\">\n<h2>在视图外使用会话<a class=\"heading-anchor\" href=\"#using-sessions-out-of-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>本节中的示例直接从 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions.backends.db</span></code> 后端导入 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 对象。在你自己的代码中，你应该考虑从由 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 指定的会话引擎中导入 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code>，如下所示：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">importlib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">import_module</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">SessionStore</span> <span class=\"o\">=</span> <span class=\"n\">import_module</span><span class=\"p\">(</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">SESSION_ENGINE</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">SessionStore</span>\n</code></pre></div>\n</aside>\n<p>在视图之外，有一个 API 可用于操作会话数据：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.sessions.backends.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SessionStore</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span> <span class=\"o\">=</span> <span class=\"n\">SessionStore</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"c1\"># stored as seconds since epoch since datetimes are not serializable in JSON.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"s2\">&quot;last_login&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"mi\">1376587691</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"o\">.</span><span class=\"n\">session_key</span>\n<span class=\"go\">&#39;2b1189a188b44ad18c35e113ac6ceead&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span> <span class=\"o\">=</span> <span class=\"n\">SessionStore</span><span class=\"p\">(</span><span class=\"n\">session_key</span><span class=\"o\">=</span><span class=\"s2\">&quot;2b1189a188b44ad18c35e113ac6ceead&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"p\">[</span><span class=\"s2\">&quot;last_login&quot;</span><span class=\"p\">]</span>\n<span class=\"go\">1376587691</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore.create()</span></code> 用于创建一个新的会话（即，一个未从会话存储加载并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">session_key=None</span></code> 的会话）。<code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> 用于保存一个已存在的会话（即，从会话存储加载的会话）。在新会话上调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> 也可能有效，但有小概率生成与现有会话冲突的 <code class=\"docutils literal notranslate\"><span class=\"pre\">session_key</span></code>。<code class=\"docutils literal notranslate\"><span class=\"pre\">create()</span></code> 调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> 并循环直到生成一个未使用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">session_key</span></code>。</p>\n<p>如果你使用的是 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions.backends.db</span></code> 后端，每个会话都是一个普通的 Django 模型。<code class=\"docutils literal notranslate\"><span class=\"pre\">Session</span></code> 模型在 <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/6.0.x/django/contrib/sessions/models.py\">django/contrib/sessions/models.py</a> 中定义。因为它是一个普通的模型，所以你可以使用普通的 Django 数据库 API 访问会话：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.sessions.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Session</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span> <span class=\"o\">=</span> <span class=\"n\">Session</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"s2\">&quot;2b1189a188b44ad18c35e113ac6ceead&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"o\">.</span><span class=\"n\">expire_date</span>\n<span class=\"go\">datetime.datetime(2005, 8, 20, 13, 35, 12)</span>\n</code></pre></div>\n<p>Note that you'll need to call\n<a class=\"reference internal\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.get_decoded\" title=\"django.contrib.sessions.base_session.AbstractBaseSession.get_decoded\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_decoded()</span></code></a> to get the session\ndictionary. This is necessary because the dictionary is stored in an encoded\nformat:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"o\">.</span><span class=\"n\">session_data</span>\n<span class=\"go\">&#39;KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">s</span><span class=\"o\">.</span><span class=\"n\">get_decoded</span><span class=\"p\">()</span>\n<span class=\"go\">{&#39;user_id&#39;: 42}</span>\n</code></pre></div>\n</section>\n<section id=\"when-sessions-are-saved\">\n<h2>当会话被保存时<a class=\"heading-anchor\" href=\"#when-sessions-are-saved\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>默认情况下，只有当会话被修改时，Django 才会保存到会话数据库，也就是说，如果它的字典值中有任何一个被赋值或删除：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># Session is modified.</span>\n<span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;bar&quot;</span>\n\n<span class=\"c1\"># Session is modified.</span>\n<span class=\"k\">del</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">]</span>\n\n<span class=\"c1\"># Session is modified.</span>\n<span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n\n<span class=\"c1\"># Gotcha: Session is NOT modified, because this alters</span>\n<span class=\"c1\"># request.session[&#39;foo&#39;] instead of request.session.</span>\n<span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">][</span><span class=\"s2\">&quot;bar&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;baz&quot;</span>\n</code></pre></div>\n<p>在上面的示例的最后一种情况中，我们可以通过在会话对象上设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">modified</span></code> 属性来明确告诉会话对象它已被修改：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">modified</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n</code></pre></div>\n<p>要更改这个默认行为，将 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_SAVE_EVERY_REQUEST</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。当设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，Django 将在每个请求上将会话保存到数据库中。</p>\n<p>请注意，只有在创建或修改会话时才会发送会话 cookie。如果 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_SAVE_EVERY_REQUEST</span></code></a> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，则会在每个请求上发送会话 cookie。</p>\n<p>类似地，会话 cookie 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">expires</span></code> 部分在每次发送会话 cookie 时都会更新。</p>\n<p>如果响应状态代码为 500，会话不会被保存。</p>\n</section>\n<section id=\"browser-length-sessions-vs-persistent-sessions\">\n<span id=\"browser-length-vs-persistent-sessions\"></span><h2>浏览器长度会话与持久会话<a class=\"heading-anchor\" href=\"#browser-length-sessions-vs-persistent-sessions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>你可以使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a> 设置来控制会话框架是否使用浏览器长度会话还是持久会话。</p>\n<p>默认情况下， <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>，这意味着会话 cookie 将在用户的浏览器中存储，时间为 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a> 的值。如果你不希望用户每次打开浏览器时都要登录，可以使用这个设置。</p>\n<p>如果 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，Django 将使用浏览器长度的 cookie -- 即当用户关闭浏览器时立即过期的 cookie。如果你希望用户每次打开浏览器时都需要登录，可以使用这个设置。</p>\n<p>这个设置是全局默认设置，可以通过在每个会话级别上显式调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.session</span></code> 的 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.set_expiry\" title=\"django.contrib.sessions.backends.base.SessionBase.set_expiry\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_expiry()</span></code></a> 方法来覆盖，如上面在 <a class=\"reference internal\" href=\"#using-sessions-in-views\">在视图中使用会话</a> 部分所述。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>一些浏览器（例如Chrome）提供了允许用户在关闭并重新打开浏览器后继续浏览会话的设置。在某些情况下，这可能会影响到 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a> 设置，并阻止会话在关闭浏览器时过期。在测试启用了 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a> 设置的 Django 应用程序时，请注意这一点。</p>\n</aside>\n</section>\n<section id=\"clearing-the-session-store\">\n<span id=\"id2\"></span><h2>清除会话存储<a class=\"heading-anchor\" href=\"#clearing-the-session-store\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>随着用户在你的网站上创建新的会话，会话数据可能会在你的会话存储中累积。如果你使用的是数据库后端，<code class=\"docutils literal notranslate\"><span class=\"pre\">django_session</span></code> 数据库表会增长。如果你使用的是文件后端，你的临时目录会包含越来越多的文件。</p>\n<p>要理解这个问题，考虑一下数据库后端的情况。当用户登录时，Django 会向 <code class=\"docutils literal notranslate\"><span class=\"pre\">django_session</span></code> 数据库表添加一行记录。每当会话数据发生更改时，Django 会更新此行记录。如果用户手动注销，Django 会删除这行记录。但如果用户没有注销，这行记录永远不会被删除。文件后端也有类似的过程。</p>\n<p>Django <em>不会</em> 自动清除过期的会话。因此，你需要定期清除过期的会话。Django 为此提供了一个清理管理命令：<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-clearsessions\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">clearsessions</span></code></a>。建议定期调用这个命令，例如作为每日的 cron 作业。</p>\n<p>请注意，缓存后端不会受到这个问题的影响，因为缓存会自动删除过时的数据。同样，cookie 后端也不会受到影响，因为会话数据是由用户的浏览器存储的。</p>\n</section>\n<section id=\"settings\">\n<h2>配置<a class=\"heading-anchor\" href=\"#settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>一些 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#settings-sessions\"><span class=\"std std-ref\">Django 设置</span></a> 允许你控制会话的行为：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_CACHE_ALIAS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_CACHE_ALIAS</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_AGE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_DOMAIN\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_DOMAIN</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_HTTPONLY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_HTTPONLY</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_NAME</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_PATH</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_SAMESITE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_SAMESITE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_SECURE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_SECURE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_EXPIRE_AT_BROWSER_CLOSE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_EXPIRE_AT_BROWSER_CLOSE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_FILE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_FILE_PATH</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_SAVE_EVERY_REQUEST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_SAVE_EVERY_REQUEST</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_SERIALIZER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_SERIALIZER</span></code></a></p></li>\n</ul>\n</section>\n<section id=\"session-security\">\n<span id=\"topics-session-security\"></span><h2>会话安全<a class=\"heading-anchor\" href=\"#session-security\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>站点内的子域名可以在整个域上为客户端设置 cookie。如果允许来自不受信任用户控制的子域的 cookie，这将可能导致会话固定。</p>\n<p>例如，攻击者可以登录到 <code class=\"docutils literal notranslate\"><span class=\"pre\">good.example.com</span></code> 并获得他们账户的有效会话。如果攻击者控制 <code class=\"docutils literal notranslate\"><span class=\"pre\">bad.example.com</span></code>，他们可以使用它来将他们的会话密钥发送给你，因为子域名被允许在 <code class=\"docutils literal notranslate\"><span class=\"pre\">*.example.com</span></code> 上设置 cookie。当你访问 <code class=\"docutils literal notranslate\"><span class=\"pre\">good.example.com</span></code> 时，你将以攻击者的身份登录，并可能不小心将你的敏感个人数据（如信用卡信息）输入到攻击者的帐户中。</p>\n<p>另一个可能的攻击是，如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">good.example.com</span></code> 将其 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_COOKIE_DOMAIN\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_COOKIE_DOMAIN</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;example.com&quot;</span></code>，这将导致该站点的会话 cookie 被发送到 <code class=\"docutils literal notranslate\"><span class=\"pre\">bad.example.com</span></code>。</p>\n</section>\n<section id=\"technical-details\">\n<h2>技术细节<a class=\"heading-anchor\" href=\"#technical-details\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<ul class=\"simple\">\n<li><p>当使用 <a class=\"reference internal\" href=\"#django.contrib.sessions.serializers.JSONSerializer\" title=\"django.contrib.sessions.serializers.JSONSerializer\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">JSONSerializer</span></code></a> 时，会话字典接受任何可以进行 <a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#module-json\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">json</span></code></a> 序列化的值。</p></li>\n<li><p>会话数据保存在名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django_session</span></code> 的数据库表中。</p></li>\n<li><p>Django 只有它需要的时候才会发送 cookie 。如果你不想设置任何会话数据，它将不会发送会话 cookie 。</p></li>\n</ul>\n<section id=\"the-sessionstore-object\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 对象<a class=\"heading-anchor\" href=\"#the-sessionstore-object\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在内部处理会话时，Django 使用相应会话引擎的会话存储对象。按照约定，会话存储对象类的名称为 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code>，并位于由 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-SESSION_ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SESSION_ENGINE</span></code></a> 指定的模块中。</p>\n<p>Django 中所有可用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 子类都实现了以下数据操作方法：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">exists()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">create()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">delete()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">load()</span></code></p></li>\n<li><p><a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.clear_expired\" title=\"django.contrib.sessions.backends.base.SessionBase.clear_expired\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">clear_expired()</span></code></a></p></li>\n</ul>\n<p>通过使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">sync_to_async()</span></code> 包装这些方法，提供了它们的异步接口。如果有原生的异步实现，可以直接实现它们：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">aexists()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">acreate()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">asave()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">adelete()</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">aload()</span></code></p></li>\n<li><p><a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase.aclear_expired\" title=\"django.contrib.sessions.backends.base.SessionBase.aclear_expired\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">aclear_expired()</span></code></a></p></li>\n</ul>\n<p>为了构建自定义的会话引擎或自定义现有的引擎，你可以创建一个继承自 <a class=\"reference internal\" href=\"#django.contrib.sessions.backends.base.SessionBase\" title=\"django.contrib.sessions.backends.base.SessionBase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SessionBase</span></code></a> 或任何其他现有的 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 类的新类。</p>\n<p>你可以扩展会话引擎，但通常在使用数据库后端的会话引擎时需要额外的努力（详见下一节的详细信息）。</p>\n</section>\n</section>\n<section id=\"extending-database-backed-session-engines\">\n<span id=\"id3\"></span><h2>扩展数据库后端的会话引擎<a class=\"heading-anchor\" href=\"#extending-database-backed-session-engines\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>可以通过继承 <a class=\"reference internal\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession\" title=\"django.contrib.sessions.base_session.AbstractBaseSession\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseSession</span></code></a> 和任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 类来创建一个基于 Django 中包含的数据库后端会话引擎（即 <code class=\"docutils literal notranslate\"><span class=\"pre\">db</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">cached_db</span></code> ）的自定义会话引擎。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">AbstractBaseSession</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">BaseSessionManager</span></code> 可以从 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions.base_session</span></code> 中导入，这样可以在 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 中不包括 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions</span></code> 的情况下导入它们。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">base_session.</span></span><span class=\"sig-name descname\"><span class=\"pre\">AbstractBaseSession</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>抽象的基础会话模型。</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession.session_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">session_key</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.session_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>主键。该字段本身最多可包含 40 个字符。当前的实现生成一个 32 个字符的字符串（由数字和小写 ASCII 字母的随机序列组成）。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession.session_data\">\n<span class=\"sig-name descname\"><span class=\"pre\">session_data</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.session_data\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个包含编码和序列化的会话字典的字符串。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession.expire_date\">\n<span class=\"sig-name descname\"><span class=\"pre\">expire_date</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.expire_date\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个指示会话过期时间的日期时间。</p>\n<p>已过期的会话对用户不可用，但它们仍然可能存储在数据库中，直到运行 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/django-admin/#django-admin-clearsessions\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">clearsessions</span></code></a> 管理命令。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession.get_session_store_class\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">get_session_store_class</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.get_session_store_class\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回一个与此会话模型一起使用的会话存储类。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.AbstractBaseSession.get_decoded\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_decoded</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.AbstractBaseSession.get_decoded\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回解码后的会话数据。</p>\n<p>解码由会话存储类执行。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p>你还可以通过继承 <a class=\"reference internal\" href=\"#django.contrib.sessions.base_session.BaseSessionManager\" title=\"django.contrib.sessions.base_session.BaseSessionManager\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BaseSessionManager</span></code></a> 来自定义模型管理器：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.BaseSessionManager\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">base_session.</span></span><span class=\"sig-name descname\"><span class=\"pre\">BaseSessionManager</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.BaseSessionManager\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.BaseSessionManager.encode\">\n<span class=\"sig-name descname\"><span class=\"pre\">encode</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">session_dict</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.BaseSessionManager.encode\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>将给定的会话字典序列化并编码为字符串后返回。</p>\n<p>编码由与模型类相关联的会话存储类执行。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.base_session.BaseSessionManager.save\">\n<span class=\"sig-name descname\"><span class=\"pre\">save</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">session_key</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">session_dict</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expire_date</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.base_session.BaseSessionManager.save\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>保存提供的会话键的会话数据，如果数据为空，则删除该会话。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p>通过覆盖下面描述的方法和属性来实现对 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code> 类的定制：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.db.SessionStore\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">backends.db.</span></span><span class=\"sig-name descname\"><span class=\"pre\">SessionStore</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.db.SessionStore\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>实现基于数据库的会话存储。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.db.SessionStore.get_model_class\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">get_model_class</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.db.SessionStore.get_model_class\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>如果需要，覆盖此方法以返回自定义的会话模型。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.db.SessionStore.create_model_instance\">\n<span class=\"sig-name descname\"><span class=\"pre\">create_model_instance</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.db.SessionStore.create_model_instance\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回一个新的会话模型对象实例，该对象表示当前会话状态。</p>\n<p>覆盖此方法可以在数据保存到数据库之前修改会话模型数据。</p>\n</dd></dl>\n\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.cached_db.SessionStore\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">backends.cached_db.</span></span><span class=\"sig-name descname\"><span class=\"pre\">SessionStore</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.cached_db.SessionStore\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>实现了基于缓存的数据库后端的会话存储。</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.sessions.backends.cached_db.SessionStore.cache_key_prefix\">\n<span class=\"sig-name descname\"><span class=\"pre\">cache_key_prefix</span></span><a class=\"heading-anchor\" href=\"#django.contrib.sessions.backends.cached_db.SessionStore.cache_key_prefix\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>用于构建缓存键字符串的会话键前缀。</p>\n</dd></dl>\n\n</dd></dl>\n\n<section id=\"example\">\n<h3>例如<a class=\"heading-anchor\" href=\"#example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>下面的示例展示了一个自定义的基于数据库的会话引擎，其中包括一个额外的数据库列来存储账户 ID（从而提供了查询账户的所有活动会话的选项）：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.sessions.backends.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SessionStore</span> <span class=\"k\">as</span> <span class=\"n\">DBStore</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.sessions.base_session</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AbstractBaseSession</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomSession</span><span class=\"p\">(</span><span class=\"n\">AbstractBaseSession</span><span class=\"p\">):</span>\n    <span class=\"n\">account_id</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">(</span><span class=\"n\">null</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span> <span class=\"n\">db_index</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_session_store_class</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">SessionStore</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SessionStore</span><span class=\"p\">(</span><span class=\"n\">DBStore</span><span class=\"p\">):</span>\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_model_class</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">CustomSession</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_model_instance</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">data</span><span class=\"p\">):</span>\n        <span class=\"n\">obj</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">create_model_instance</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"p\">)</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"n\">account_id</span> <span class=\"o\">=</span> <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"n\">data</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;_auth_user_id&quot;</span><span class=\"p\">))</span>\n        <span class=\"k\">except</span> <span class=\"p\">(</span><span class=\"ne\">ValueError</span><span class=\"p\">,</span> <span class=\"ne\">TypeError</span><span class=\"p\">):</span>\n            <span class=\"n\">account_id</span> <span class=\"o\">=</span> <span class=\"kc\">None</span>\n        <span class=\"n\">obj</span><span class=\"o\">.</span><span class=\"n\">account_id</span> <span class=\"o\">=</span> <span class=\"n\">account_id</span>\n        <span class=\"k\">return</span> <span class=\"n\">obj</span>\n</code></pre></div>\n<p>如果你正在从 Django 内置的 <code class=\"docutils literal notranslate\"><span class=\"pre\">cached_db</span></code> 会话存储迁移到一个基于 <code class=\"docutils literal notranslate\"><span class=\"pre\">cached_db</span></code> 的自定义存储，你应该覆盖缓存键前缀以防止命名空间冲突：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SessionStore</span><span class=\"p\">(</span><span class=\"n\">CachedDBStore</span><span class=\"p\">):</span>\n    <span class=\"n\">cache_key_prefix</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;mysessions.custom_cached_db_backend&quot;</span>\n\n    <span class=\"c1\"># ...</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"session-ids-in-urls\">\n<h2>URL 中的会话 ID<a class=\"heading-anchor\" href=\"#session-ids-in-urls\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 会话框架完全且仅基于 cookie。与 PHP 不同，它不会作为最后的手段将会话 ID 放在 URL 中。这是一个有意的设计决策。这种行为不仅会使 URL 变得难看，还会使你的网站容易受到通过&quot;Referer&quot;头部进行会话 ID 窃取的攻击。</p>\n</section>","rootId":"module-django.contrib.sessions","toc":[{"title":"启用会话","anchor":"enabling-sessions","children":[]},{"title":"配置会话引擎","anchor":"configuring-the-session-engine","children":[{"title":"使用基于数据库的会话","anchor":"using-database-backed-sessions","children":[]},{"title":"使用缓存会话","anchor":"using-cached-sessions","children":[]},{"title":"使用基于文件的会话","anchor":"using-file-based-sessions","children":[]},{"title":"使用基于 cookie 的会话","anchor":"using-cookie-based-sessions","children":[]}]},{"title":"在视图中使用会话","anchor":"using-sessions-in-views","children":[{"title":"会话序列化","anchor":"session-serialization","children":[{"title":"捆绑的序列化器","anchor":"bundled-serializers","children":[]},{"title":"编写你自己的序列化器","anchor":"write-your-own-serializer","children":[]}]},{"title":"会话对象指南","anchor":"session-object-guidelines","children":[]},{"title":"示例","anchor":"examples","children":[]}]},{"title":"设置测试 cookie","anchor":"setting-test-cookies","children":[]},{"title":"在视图外使用会话","anchor":"using-sessions-out-of-views","children":[]},{"title":"当会话被保存时","anchor":"when-sessions-are-saved","children":[]},{"title":"浏览器长度会话与持久会话","anchor":"browser-length-sessions-vs-persistent-sessions","children":[]},{"title":"清除会话存储","anchor":"clearing-the-session-store","children":[]},{"title":"配置","anchor":"settings","children":[]},{"title":"会话安全","anchor":"session-security","children":[]},{"title":"技术细节","anchor":"technical-details","children":[{"title":"SessionStore 对象","anchor":"the-sessionstore-object","children":[]}]},{"title":"扩展数据库后端的会话引擎","anchor":"extending-database-backed-session-engines","children":[{"title":"例如","anchor":"example","children":[]}]},{"title":"URL 中的会话 ID","anchor":"session-ids-in-urls","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/6.0/topics/"},{"docname":"topics/http/index","title":"处理 HTTP 请求","url":"/zh-hans/6.0/topics/http/"}],"prev":{"docname":"topics/http/middleware","title":"中间件","url":"/zh-hans/6.0/topics/http/middleware/"},"next":{"docname":"topics/forms/index","title":"使用表单","url":"/zh-hans/6.0/topics/forms/"},"formats":{"html":"/zh-hans/6.0/topics/http/sessions/","markdown":"/zh-hans/6.0/topics/http/sessions.md","json":"/zh-hans/6.0/topics/http/sessions.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/http/sessions.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/topics/http/sessions/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}