{"title":"使用 Django 的验证系统","version":"3.0","locale":"zh-hans","docname":"topics/auth/default","url":"/zh-hans/3.0/topics/auth/default/","canonical":"https://djangodocs.dev/zh-hans/3.0/topics/auth/default/","summary":"本文档介绍了 Django 验证系统在默认配置下的使用方法。默认配置满足最常见的项目需求，可以处理相当多的任务，还有一个安全的密码和权限实现。对于验证需求与默认配置不同的项目，Django 支持对身份验证进行扩展和定制。 Django 验证同时提供身份验证和授权，通常称为身份验证系统，因为这些功能在某种程度上是耦合的。…","html":"<h1>使用 Django 的验证系统<a class=\"heading-anchor\" href=\"#using-the-django-authentication-system\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>本文档介绍了 Django 验证系统在默认配置下的使用方法。默认配置满足最常见的项目需求，可以处理相当多的任务，还有一个安全的密码和权限实现。对于验证需求与默认配置不同的项目，Django 支持对身份验证进行扩展和定制。</p>\n<p>Django 验证同时提供身份验证和授权，通常称为身份验证系统，因为这些功能在某种程度上是耦合的。</p>\n<section id=\"user-objects\">\n<span id=\"id1\"></span><h2><code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 对象<a class=\"heading-anchor\" href=\"#user-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>用户对象是认证系统的核心。它通常代表了与你的站点交互的人员，并用于允许诸如限制访问、注册用户配置文件、将内容与创建者关联等功能。Django 的认证框架中用户只有一个类，例如 “超级管理员”或“普通管理员”只是具有特殊属性集的用户对象，而不是用户对象的不同类。</p>\n<p>默认用户的主要属性是：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.username\" title=\"django.contrib.auth.models.User.username\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">username</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.password\" title=\"django.contrib.auth.models.User.password\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">password</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.email\" title=\"django.contrib.auth.models.User.email\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">email</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.first_name\" title=\"django.contrib.auth.models.User.first_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">first_name</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.last_name\" title=\"django.contrib.auth.models.User.last_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">last_name</span></code></a></p></li>\n</ul>\n<p>请参阅完整的API文档 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">full</span> <span class=\"pre\">API</span> <span class=\"pre\">documentation</span></code></a> 以获得完整的参考，下面的文档主要以任务为导向。</p>\n<section id=\"creating-users\">\n<span id=\"topics-auth-creating-users\"></span><h3>创建用户<a class=\"heading-anchor\" href=\"#creating-users\"><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/3.0/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user\" title=\"django.contrib.auth.models.UserManager.create_user\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">create_user()</span></code></a> 的函数：</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=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create_user</span><span class=\"p\">(</span><span class=\"s1\">&#39;john&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;lennon@thebeatles.com&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;johnpassword&#39;</span><span class=\"p\">)</span>\n\n<span class=\"go\"># At this point, user is a User object that has already been saved</span>\n<span class=\"go\"># to the database. You can continue to change its attributes</span>\n<span class=\"go\"># if you want to change other fields.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">last_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;Lennon&#39;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>如果你已经安装了 Django admin 管理后台，你也可以在 admin 管理后台交互式地创建用户:ref:create users interactively &lt;auth-admin&gt; 。</p>\n</section>\n<section id=\"creating-superusers\">\n<span id=\"topics-auth-creating-superusers\"></span><h3>创建超级用户<a class=\"heading-anchor\" href=\"#creating-superusers\"><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/3.0/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> 创建超级管理员：</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>$ python manage.py createsuperuser --username=joe --email=joe@example.com\n</code></pre></div>\n<p>你将会被提示输入密码，完成之后，超级管理员就被创建成功了。如果你没有填写参数 <code class=\"xref std std-option docutils literal notranslate\"><span class=\"pre\">--username</span> <span class=\"pre\">&lt;createsuperuser</span> <span class=\"pre\">--username&gt;</span> <span class=\"pre\">`</span> <span class=\"pre\">or</span> <span class=\"pre\">:option:</span></code>--email &lt;createsuperuser --email&gt;` ，也将会被提示输入这些值。</p>\n</section>\n<section id=\"changing-passwords\">\n<h3>更改密码<a class=\"heading-anchor\" href=\"#changing-passwords\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 不会在用户模型里保存原始(明文)密码，而只会存储哈希值(请参阅文档 如何管理密码  <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/passwords/\"><span class=\"doc\">documentation of how passwords are managed</span></a> ) 。因此，请不要试图直接操作用户的密码，这就是创建用户需要辅助函数的原因。</p>\n<p>更改一个用户的密码，你有几个选择：</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-changepassword\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">changepassword</span> <span class=\"pre\">*username*</span></code></a> 提供了在命令行修改用户密码的方法。它会提示你输入两次新密码，如果操作成功，新密码就立刻生效。如果你没有提供参数 username ，那么将会尝试修改当前系统用户的密码。</p>\n<p>你也可以在代码里修改密码，使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password\" title=\"django.contrib.auth.models.User.set_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_password()</span></code></a>:</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.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">u</span> <span class=\"o\">=</span> <span class=\"n\">User</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=\"s1\">&#39;john&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">u</span><span class=\"o\">.</span><span class=\"n\">set_password</span><span class=\"p\">(</span><span class=\"s1\">&#39;new password&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">u</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>如果你已经按照了 Django admin 管理后台，你也可以在管理后台页面修改密码（请参阅 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>authentication system's admin pages ` ）。</p>\n<p>Django 还提供了允许用户自行修改密码的 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>views ` 和 :ref:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>forms ` 。</p>\n<p>修改密码将会注销用户的所有会话。查看详情请参阅 <a class=\"reference internal\" href=\"#session-invalidation-on-password-change\"><span class=\"std std-ref\">密码更改时会话失效</span></a> 。</p>\n</section>\n<section id=\"authenticating-users\">\n<h3>验证用户<a class=\"heading-anchor\" href=\"#authenticating-users\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.authenticate\">\n<span class=\"sig-name descname\"><span class=\"pre\">authenticate</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">credentials</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.authenticate\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>使用 <a class=\"reference internal\" href=\"#django.contrib.auth.authenticate\" title=\"django.contrib.auth.authenticate\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code></a> 来验证用户。它使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">username</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> 作为参数来验证，对每个身份验证后端( <span class=\"xref std std-ref\">authentication backend ` )进行检查。如果后端验证有效，则返回一个 :class:`~django.contrib.auth.models.User</span> 对象。如果后端引发 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 错误，将返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">authenticate</span>\n<span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">authenticate</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;john&#39;</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"s1\">&#39;secret&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">if</span> <span class=\"n\">user</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n    <span class=\"c1\"># A backend authenticated the credentials</span>\n<span class=\"k\">else</span><span class=\"p\">:</span>\n    <span class=\"c1\"># No backend authenticated the credentials</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> 是可选的 <a class=\"reference internal\" href=\"/zh-hans/3.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> ，它在身份验证后端上的 <code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code> 方法来传递。</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/3.0/ref/middleware/#django.contrib.auth.middleware.RemoteUserMiddleware\" title=\"django.contrib.auth.middleware.RemoteUserMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RemoteUserMiddleware</span></code></a> 来验证。除非你在编写自己的身份验证系统，否则你可能不会用到它。如果你正在寻找用户登录的方法，请参阅 <a class=\"reference internal\" href=\"#django.contrib.auth.views.LoginView\" title=\"django.contrib.auth.views.LoginView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">LoginView</span></code></a> 。</p>\n</aside>\n</dd></dl>\n\n</section>\n</section>\n<section id=\"permissions-and-authorization\">\n<span id=\"topic-authorization\"></span><h2>权限和认证<a class=\"heading-anchor\" href=\"#permissions-and-authorization\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 内置了一个权限系统。它提供了为指定的用户和用户组分配权限的方法。</p>\n<p>它在 Django 管理后台界面里使用，但你也可以在自己的代码中使用它。</p>\n<p>Django 的 admin 页面使用了如下权限：</p>\n<ul class=\"simple\">\n<li><p>访问查看的对象仅限于具有该类型对象的“查看”或“更改”权限的用户。</p></li>\n<li><p>访问“添加”表单和添加对象仅限于具有该类型对象的“添加”权限的用户。</p></li>\n<li><p>访问修改列表、查看“修改”表单和修改对象仅限于对该类型对象的“修改”权限的用户。</p></li>\n<li><p>访问删除对象仅限于对该类型对象的“删除”权限的用户。</p></li>\n</ul>\n<p>不仅可以为每个对象类型设置权限，还可以为每个指定对象实例设置权限。通过使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin\" title=\"django.contrib.admin.ModelAdmin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelAdmin</span></code></a> 类提供的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_view_permission\" title=\"django.contrib.admin.ModelAdmin.has_view_permission\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_view_permission()</span></code></a>, <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_add_permission\" title=\"django.contrib.admin.ModelAdmin.has_add_permission\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_add_permission()</span></code></a>, <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_change_permission\" title=\"django.contrib.admin.ModelAdmin.has_change_permission\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_change_permission()</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_delete_permission\" title=\"django.contrib.admin.ModelAdmin.has_delete_permission\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_delete_permission()</span></code></a> 方法，可以为同一类型的不同实例定制权限。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 对象有两个多对多字段:<code class=\"docutils literal notranslate\"><span class=\"pre\">groups</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_permissions</span></code>。 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 对象可以像访问其他 :doc:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>Django model <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>: 一样访问他们的相关对象。</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\">myuser</span><span class=\"o\">.</span><span class=\"n\">groups</span><span class=\"o\">.</span><span class=\"n\">set</span><span class=\"p\">([</span><span class=\"n\">group_list</span><span class=\"p\">])</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">groups</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">group</span><span class=\"p\">,</span> <span class=\"n\">group</span><span class=\"p\">,</span> <span class=\"o\">...</span><span class=\"p\">)</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">groups</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">group</span><span class=\"p\">,</span> <span class=\"n\">group</span><span class=\"p\">,</span> <span class=\"o\">...</span><span class=\"p\">)</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">groups</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">set</span><span class=\"p\">([</span><span class=\"n\">permission_list</span><span class=\"p\">])</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">permission</span><span class=\"p\">,</span> <span class=\"n\">permission</span><span class=\"p\">,</span> <span class=\"o\">...</span><span class=\"p\">)</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">permission</span><span class=\"p\">,</span> <span class=\"n\">permission</span><span class=\"p\">,</span> <span class=\"o\">...</span><span class=\"p\">)</span>\n<span class=\"n\">myuser</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">clear</span><span class=\"p\">()</span>\n</code></pre></div>\n<section id=\"default-permissions\">\n<h3>默认权限<a class=\"heading-anchor\" href=\"#default-permissions\"><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/3.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.auth</span></code> 时，它将确保你的每个 Django 模型被创建时有四个默认权限：添加、修改、删除和查看。</p>\n<p>运行 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code></a> 时将创建这些权限。当你添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code> 到 <a class=\"reference internal\" href=\"/zh-hans/3.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\">迁移</span></code> ，将会为所有只去已经安装过的模型以及现在正在安装的模型创建这些默认的权限。之后，每次你运行 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code></a> 都会为新模型创建默认权限 (创建权限的函数连接 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/signals/#django.db.models.signals.post_migrate\" title=\"django.db.models.signals.post_migrate\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">post_migrate</span></code></a> 信号)。</p>\n<p>假设你有一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></code> 应用程序和一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">Bar</span></code> 的模型，要测试基础权限，你应该使用：</p>\n<ul class=\"simple\">\n<li><p>添加：<code class=\"docutils literal notranslate\"><span class=\"pre\">user.has_perm('foo.add_bar')</span></code></p></li>\n<li><p>修改：<code class=\"docutils literal notranslate\"><span class=\"pre\">user.has_perm('foo.change_bar')</span></code></p></li>\n<li><p>删除：<code class=\"docutils literal notranslate\"><span class=\"pre\">user.has_perm('foo.delete_bar')</span></code></p></li>\n<li><p>查看：<code class=\"docutils literal notranslate\"><span class=\"pre\">user.has_perm('foo.view_bar')</span></code></p></li>\n</ul>\n<p>权限模型很少会被直接访问。</p>\n</section>\n<section id=\"groups\">\n<h3>组<a class=\"heading-anchor\" href=\"#groups\"><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/3.0/ref/contrib/auth/#django.contrib.auth.models.Group\" title=\"django.contrib.auth.models.Group\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.models.Group</span></code></a> 模型是对用户进行分类的通用方法，因此您可以将权限或其他标签应用于这些用户。用户可以属于任意数量的组。</p>\n<p>组里的用户会自动拥有该组的权限。举例，如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">Site</span> <span class=\"pre\">editors</span></code> 组有修改网站首页的权限，那么该组的任何成员都有这个权限。</p>\n<p>除权限外，组是一个方便的途径，可以给用户分类，为其提供一些标签或扩展功能。例如，你可以创建一个组 <code class=\"docutils literal notranslate\"><span class=\"pre\">'Special</span> <span class=\"pre\">users'</span></code>，并在编写的代码里让该组成员访问网站仅限会员部分的内容，或者对该组成员发送仅限会员查看的电子邮件。</p>\n</section>\n<section id=\"programmatically-creating-permissions\">\n<h3>以编程方式创建权限<a class=\"heading-anchor\" href=\"#programmatically-creating-permissions\"><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\">Meta</span></code> 类中定义 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#custom-permissions\"><span class=\"std std-ref\">custom permissions</span></a> ，你也可以直接创建权限。例如，你可以为 <code class=\"docutils literal notranslate\"><span class=\"pre\">BlogPost</span></code> 模型创建 <code class=\"docutils literal notranslate\"><span class=\"pre\">can_publish</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BlogPost</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Permission</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.contenttypes.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ContentType</span>\n\n<span class=\"n\">content_type</span> <span class=\"o\">=</span> <span class=\"n\">ContentType</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get_for_model</span><span class=\"p\">(</span><span class=\"n\">BlogPost</span><span class=\"p\">)</span>\n<span class=\"n\">permission</span> <span class=\"o\">=</span> <span class=\"n\">Permission</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span>\n    <span class=\"n\">codename</span><span class=\"o\">=</span><span class=\"s1\">&#39;can_publish&#39;</span><span class=\"p\">,</span>\n    <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;Can Publish Posts&#39;</span><span class=\"p\">,</span>\n    <span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"n\">content_type</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>然后，可以通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_permissions</span></code> 属性将权限分配给 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> ，或通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">permissions</span></code> 属性分配给 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.Group\" title=\"django.contrib.auth.models.Group\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Group</span></code></a>  。</p>\n<aside class=\"admonition-proxy-models-need-their-own-content-type admonition\">\n<p class=\"admonition-title\">代理模型需要自己的内容类型</p>\n<p>如果你想创建 <a class=\"reference internal\" href=\"#proxy-models-permissions-topic\"><span class=\"std std-ref\">permissions for a proxy model</span></a> ，传递 <code class=\"docutils literal notranslate\"><span class=\"pre\">for_concrete_model=False</span></code> 到 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentTypeManager.get_for_model\" title=\"django.contrib.contenttypes.models.ContentTypeManager.get_for_model\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ContentTypeManager.get_for_model()</span></code></a> 来获取合适的 <code class=\"docutils literal notranslate\"><span class=\"pre\">ContentType</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\">content_type</span> <span class=\"o\">=</span> <span class=\"n\">ContentType</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get_for_model</span><span class=\"p\">(</span><span class=\"n\">BlogPostProxy</span><span class=\"p\">,</span> <span class=\"n\">for_concrete_model</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"2.2\">\n<p class=\"version-note-title\">Changed in Django 2.2</p><p>在旧版本中，代理模型使用具体模型的内容类型。</p>\n</aside>\n</aside>\n</section>\n<section id=\"permission-caching\">\n<h3>权限缓存<a class=\"heading-anchor\" href=\"#permission-caching\"><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/3.0/ref/contrib/auth/#django.contrib.auth.backends.ModelBackend\" title=\"django.contrib.auth.backends.ModelBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code></a> 才会缓存它们的权限。对于请求-响应周期来说，这通常是很好的，因为权限通常不会在添加的时候立刻检查（例如，在 admin 中）。如果你打算在测试或视图中添加权限，并随后检查他们，最简单的解决方案就是从数据库中重新获取用户。例如：</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.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Permission</span><span class=\"p\">,</span> <span class=\"n\">User</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.contenttypes.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ContentType</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\">get_object_or_404</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BlogPost</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">user_gains_perms</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">user_id</span><span class=\"p\">):</span>\n    <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">(</span><span class=\"n\">User</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">user_id</span><span class=\"p\">)</span>\n    <span class=\"c1\"># any permission check will cache the current set of permissions</span>\n    <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;myapp.change_blogpost&#39;</span><span class=\"p\">)</span>\n\n    <span class=\"n\">content_type</span> <span class=\"o\">=</span> <span class=\"n\">ContentType</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get_for_model</span><span class=\"p\">(</span><span class=\"n\">BlogPost</span><span class=\"p\">)</span>\n    <span class=\"n\">permission</span> <span class=\"o\">=</span> <span class=\"n\">Permission</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span>\n        <span class=\"n\">codename</span><span class=\"o\">=</span><span class=\"s1\">&#39;change_blogpost&#39;</span><span class=\"p\">,</span>\n        <span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"n\">content_type</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">permission</span><span class=\"p\">)</span>\n\n    <span class=\"c1\"># Checking the cached permission set</span>\n    <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;myapp.change_blogpost&#39;</span><span class=\"p\">)</span>  <span class=\"c1\"># False</span>\n\n    <span class=\"c1\"># Request new instance of User</span>\n    <span class=\"c1\"># Be aware that user.refresh_from_db() won&#39;t clear the cache.</span>\n    <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">get_object_or_404</span><span class=\"p\">(</span><span class=\"n\">User</span><span class=\"p\">,</span> <span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"n\">user_id</span><span class=\"p\">)</span>\n\n    <span class=\"c1\"># Permission cache is repopulated from the database</span>\n    <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;myapp.change_blogpost&#39;</span><span class=\"p\">)</span>  <span class=\"c1\"># True</span>\n\n    <span class=\"o\">...</span>\n</code></pre></div>\n</section>\n<section id=\"proxy-models\">\n<span id=\"proxy-models-permissions-topic\"></span><h3>代理模型<a class=\"heading-anchor\" href=\"#proxy-models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\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\">class</span><span class=\"w\"> </span><span class=\"nc\">Person</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">permissions</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"s1\">&#39;can_eat_pizzas&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Can eat pizzas&#39;</span><span class=\"p\">)]</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Student</span><span class=\"p\">(</span><span class=\"n\">Person</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">proxy</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n        <span class=\"n\">permissions</span> <span class=\"o\">=</span> <span class=\"p\">[(</span><span class=\"s1\">&#39;can_deliver_pizzas&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;Can deliver pizzas&#39;</span><span class=\"p\">)]</span>\n\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"c1\"># Fetch the content type for the proxy model.</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"n\">content_type</span> <span class=\"o\">=</span> <span class=\"n\">ContentType</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get_for_model</span><span class=\"p\">(</span><span class=\"n\">Student</span><span class=\"p\">,</span> <span class=\"n\">for_concrete_model</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"n\">student_permissions</span> <span class=\"o\">=</span> <span class=\"n\">Permission</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">content_type</span><span class=\"o\">=</span><span class=\"n\">content_type</span><span class=\"p\">)</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"p\">[</span><span class=\"n\">p</span><span class=\"o\">.</span><span class=\"n\">codename</span> <span class=\"k\">for</span> <span class=\"n\">p</span> <span class=\"ow\">in</span> <span class=\"n\">student_permissions</span><span class=\"p\">]</span>\n<span class=\"p\">[</span><span class=\"s1\">&#39;add_student&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;change_student&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;delete_student&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;view_student&#39;</span><span class=\"p\">,</span>\n<span class=\"s1\">&#39;can_deliver_pizzas&#39;</span><span class=\"p\">]</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"k\">for</span> <span class=\"n\">permission</span> <span class=\"ow\">in</span> <span class=\"n\">student_permissions</span><span class=\"p\">:</span>\n<span class=\"o\">...</span>     <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">user_permissions</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">permission</span><span class=\"p\">)</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;app.add_person&#39;</span><span class=\"p\">)</span>\n<span class=\"kc\">False</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;app.can_eat_pizzas&#39;</span><span class=\"p\">)</span>\n<span class=\"kc\">False</span>\n<span class=\"o\">&gt;&gt;&gt;</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perms</span><span class=\"p\">((</span><span class=\"s1\">&#39;app.add_student&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;app.can_deliver_pizzas&#39;</span><span class=\"p\">))</span>\n<span class=\"kc\">True</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"2.2\">\n<p class=\"version-note-title\">Changed in Django 2.2</p><p>在旧版本中，代理模型的权限使用具体模型的内容类型，而不是代理模型的内容类型。</p>\n</aside>\n</section>\n</section>\n<section id=\"authentication-in-web-requests\">\n<span id=\"auth-web-requests\"></span><h2>Web 请求的认证<a class=\"heading-anchor\" href=\"#authentication-in-web-requests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django 使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/http/sessions/\"><span class=\"doc\">sessions</span></a> 和中间件将身份验证系统挂接到请求对象中。</p>\n<p>它们在每次请求中都会提供 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.user\" title=\"django.http.HttpRequest.user\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.user</span></code></a> 属性。如果当前没有用户登录，这个属性将会被设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser\" title=\"django.contrib.auth.models.AnonymousUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AnonymousUser</span></code></a> ，否则将会被设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 实例。</p>\n<p>你可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated\" title=\"django.contrib.auth.models.User.is_authenticated\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_authenticated</span></code></a> 区分两者，例如：</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\">if</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</span><span class=\"p\">:</span>\n    <span class=\"c1\"># Do something for authenticated users.</span>\n    <span class=\"o\">...</span>\n<span class=\"k\">else</span><span class=\"p\">:</span>\n    <span class=\"c1\"># Do something for anonymous users.</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<section id=\"how-to-log-a-user-in\">\n<span id=\"id2\"></span><h3>用户如何登陆<a class=\"heading-anchor\" href=\"#how-to-log-a-user-in\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果有一个已验证的用户想附加到当前会话(session)中，将通过 <a class=\"reference internal\" href=\"#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login()</span></code></a>  函数完成。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.login\">\n<span class=\"sig-name descname\"><span class=\"pre\">login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">backend</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.auth.login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>要在视图中让用户登录，使用 <a class=\"reference internal\" href=\"#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login()</span></code></a>  。它需要 <a class=\"reference internal\" href=\"/zh-hans/3.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> 对象和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 对象。通过 Django 的 session 框架， <a class=\"reference internal\" href=\"#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login()</span></code></a> 会在 session 中保存用户的ID。</p>\n<p>注意，在匿名会话期间设置的任何数据都会在用户登录后保留在会话中。</p>\n<p>这个例子展示了如何使用 <a class=\"reference internal\" href=\"#django.contrib.auth.authenticate\" title=\"django.contrib.auth.authenticate\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code></a> 和 <a class=\"reference internal\" href=\"#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login()</span></code></a>: ：</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.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">authenticate</span><span class=\"p\">,</span> <span class=\"n\">login</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <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=\"s1\">&#39;username&#39;</span><span class=\"p\">]</span>\n    <span class=\"n\">password</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=\"s1\">&#39;password&#39;</span><span class=\"p\">]</span>\n    <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">authenticate</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">username</span><span class=\"o\">=</span><span class=\"n\">username</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"n\">password</span><span class=\"p\">)</span>\n    <span class=\"k\">if</span> <span class=\"n\">user</span> <span class=\"ow\">is</span> <span class=\"ow\">not</span> <span class=\"kc\">None</span><span class=\"p\">:</span>\n        <span class=\"n\">login</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"p\">)</span>\n        <span class=\"c1\"># Redirect to a success page.</span>\n        <span class=\"o\">...</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"c1\"># Return an &#39;invalid login&#39; error message.</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n</dd></dl>\n\n<section id=\"selecting-the-authentication-backend\">\n<h4>选择验证后端<a class=\"heading-anchor\" href=\"#selecting-the-authentication-backend\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当用户登录时，用户 ID 和用于身份验证的后端会被保存在用户会话中。允许相同的 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#authentication-backends\"><span class=\"std std-ref\">authentication backend</span></a> 在未来的请求中获取用户详情。选择要在会话中保存的验证后端如下：</p>\n<ol class=\"arabic simple\">\n<li><p>使用提供了的可选 <code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> 参数值。</p></li>\n<li><p>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">user.backend</span></code>  的值。允许配对 <a class=\"reference internal\" href=\"#django.contrib.auth.authenticate\" title=\"django.contrib.auth.authenticate\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code></a>  和 <a class=\"reference internal\" href=\"#django.contrib.auth.login\" title=\"django.contrib.auth.login\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login()</span></code></a> ：当返回用户对象时 <a class=\"reference internal\" href=\"#django.contrib.auth.authenticate\" title=\"django.contrib.auth.authenticate\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code></a>  设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">user.backend</span></code> 属性。</p></li>\n<li><p>使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 存在的 <code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> 。</p></li>\n<li><p>否则，抛出一个异常。</p></li>\n</ol>\n<p>在1和2中，<code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> 参数和 <code class=\"docutils literal notranslate\"><span class=\"pre\">user.backend</span></code> 属性应该是完整的导入路径（像 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 里的路径一样），而不是真实的后端类。</p>\n</section>\n</section>\n<section id=\"how-to-log-a-user-out\">\n<h3>用户如何登出<a class=\"heading-anchor\" href=\"#how-to-log-a-user-out\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.logout\">\n<span class=\"sig-name descname\"><span class=\"pre\">logout</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.logout\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>如果已经通过 <a class=\"reference internal\" href=\"#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> 登录的用户想退出登录，可以在视图中使用 <a class=\"reference internal\" href=\"#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> 。需要传入 <a class=\"reference internal\" href=\"/zh-hans/3.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> 对象，并且该函数不会返回值。例如：</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.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">logout</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">logout_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">logout</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">)</span>\n    <span class=\"c1\"># Redirect to a success page.</span>\n</code></pre></div>\n<p>注意，如果用户未登录，<a class=\"reference internal\" href=\"#django.contrib.auth.logout\" title=\"django.contrib.auth.logout\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">logout()</span></code></a> 不会报错。</p>\n<p>调用 <a class=\"reference internal\" href=\"#django.contrib.auth.logout\" title=\"django.contrib.auth.logout\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">logout()</span></code></a> 后，当前请求的会话数据会被全部清除。这是为了防止其他使用同一个浏览器的用户访问前一名用户的会话数据。如果想在登出后立即向用户提供的会话中放入任何内容，请在调用 <a class=\"reference internal\" href=\"#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> 之后执行此操作。</p>\n</dd></dl>\n\n</section>\n<section id=\"limiting-access-to-logged-in-users\">\n<h3>限制对未登录用户的访问<a class=\"heading-anchor\" href=\"#limiting-access-to-logged-in-users\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"the-raw-way\">\n<h4>原始方式<a class=\"heading-anchor\" href=\"#the-raw-way\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>限制访问页面最原始的办法就是检查 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated\" title=\"django.contrib.auth.models.User.is_authenticated\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.user.is_authenticated</span></code></a> 并重定向到登录页面。</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.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</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\">redirect</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</span><span class=\"p\">:</span>\n        <span class=\"k\">return</span> <span class=\"n\">redirect</span><span class=\"p\">(</span><span class=\"s1\">&#39;</span><span class=\"si\">%s</span><span class=\"s1\">?next=</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"p\">(</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">LOGIN_URL</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"p\">))</span>\n    <span class=\"c1\"># ...</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=\"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<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_authenticated</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=\"s1\">&#39;myapp/login_error.html&#39;</span><span class=\"p\">)</span>\n    <span class=\"c1\"># ...</span>\n</code></pre></div>\n</section>\n<section id=\"the-login-required-decorator\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">login_required</span></code> 装饰器<a class=\"heading-anchor\" href=\"#the-login-required-decorator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.decorators.login_required\">\n<span class=\"sig-name descname\"><span class=\"pre\">login_required</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">redirect_field_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'next'</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">login_url</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.auth.decorators.login_required\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>作为快捷方式，你可以使用 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 装饰器:</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.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">login_required</span>\n\n<span class=\"nd\">@login_required</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 会执行以下操作：</p>\n<ul class=\"simple\">\n<li><p>如果用户没有登录，会重定向到  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> ，并传递绝对路径到查询字符串中。例如： <code class=\"docutils literal notranslate\"><span class=\"pre\">/accounts/login/?next=/polls/3/</span></code> 。</p></li>\n<li><p>如果用户已经登录，则正常执行视图。视图里的代码可以假设用户已经登录了。</p></li>\n</ul>\n<p>默认情况下，成功验证时用户跳转的路径保存在名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;next&quot;</span></code> 的查询字符串参数中。如果你希望这个参数使用不同名称，请在 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 中传递可选参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">login_required</span>\n\n<span class=\"nd\">@login_required</span><span class=\"p\">(</span><span class=\"n\">redirect_field_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;my_redirect_field&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>注意，如果你提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> 值，则很可能也需要自定义登录模板，因为存储重定向路径的模板上下文变量使用的是 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> 值，而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;next&quot;</span></code> （默认情况下）。</p>\n<p><a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 也有可选参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">login_required</span>\n\n<span class=\"nd\">@login_required</span><span class=\"p\">(</span><span class=\"n\">login_url</span><span class=\"o\">=</span><span class=\"s1\">&#39;/accounts/login/&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>注意，如果你没有指定参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code> ，你需要确认 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a>  和登录视图是正确关联的。例如，使用默认方式，在 URL 配置文件里添加下面这行：</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.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span> <span class=\"k\">as</span> <span class=\"n\">auth_views</span>\n\n<span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;accounts/login/&#39;</span><span class=\"p\">,</span> <span class=\"n\">auth_views</span><span class=\"o\">.</span><span class=\"n\">LoginView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()),</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> 也接受视图方法名和 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/http/urls/#naming-url-patterns\"><span class=\"std std-ref\">named URL patterns</span></a> 。这样你可以在 URLconf 里自由地重新映射你的登录视图，而不需更新配置文件。</p>\n</dd></dl>\n\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\">login_required</span></code> 装饰器不会检查用户的 <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active</span></code> 标识状态，但默认的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 会拒绝非正常用户。</p>\n</aside>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<p>如果你打算编写自定义的 Django 管理模块视图（或需要与内置视图使用同样的权限检查），你将会发现 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/admin/#django.contrib.admin.views.decorators.staff_member_required\" title=\"django.contrib.admin.views.decorators.staff_member_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">django.contrib.admin.views.decorators.staff_member_required()</span></code></a> 装饰器是 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_required()</span></code> 的一个有用的替代方法。</p>\n</aside>\n</section>\n<section id=\"the-loginrequired-mixin\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">LoginRequired</span></code> Mixin<a class=\"heading-anchor\" href=\"#the-loginrequired-mixin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>使用基于类的视图时，可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">LoginRequiredMixin</span></code> 实现和 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_required</span></code> 相同的行为。这个 Mixin 应该在继承列表中最左侧的位置。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.LoginRequiredMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">LoginRequiredMixin</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.LoginRequiredMixin\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>如果一个视图使用 Mixin ，那么未经验证用户的所有请求都会被重定向到登录页面或者显示 HTTP 403 Forbidden 错误，这取决于 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.raise_exception\" title=\"django.contrib.auth.mixins.AccessMixin.raise_exception\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">raise_exception</span></code></a> 参数。</p>\n<p>你可以设置 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin\" title=\"django.contrib.auth.mixins.AccessMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AccessMixin</span></code></a> 的任何参数来自定义未验证用户的处理：</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.auth.mixins</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">LoginRequiredMixin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyView</span><span class=\"p\">(</span><span class=\"n\">LoginRequiredMixin</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n    <span class=\"n\">login_url</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;/login/&#39;</span>\n    <span class=\"n\">redirect_field_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;redirect_to&#39;</span>\n</code></pre></div>\n</dd></dl>\n\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\">login_required</span></code> 装饰器一样，Mixin 不会检查用户的 <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active</span></code> 标识状态，但默认的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 会拒绝非正常用户。</p>\n</aside>\n</section>\n<section id=\"limiting-access-to-logged-in-users-that-pass-a-test\">\n<h4>限制对通过测试的登录用户的访问<a class=\"heading-anchor\" href=\"#limiting-access-to-logged-in-users-that-pass-a-test\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>根据某些权限或者其他测试来限制访问，你基本上可以执行和上一节所述同样的操作。</p>\n<p>可以在视图里直接对 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.user\" title=\"django.http.HttpRequest.user\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.user</span></code></a> 进行测试。举例，这个视图检查用户是否拥有特定域名的邮箱，否则会重定向到登录页：</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.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">redirect</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">email</span><span class=\"o\">.</span><span class=\"n\">endswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;@example.com&#39;</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">redirect</span><span class=\"p\">(</span><span class=\"s1\">&#39;/login/?next=</span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"p\">)</span>\n    <span class=\"c1\"># ...</span>\n</code></pre></div>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.decorators.user_passes_test\">\n<span class=\"sig-name descname\"><span class=\"pre\">user_passes_test</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">test_func</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">login_url</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">redirect_field_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'next'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.decorators.user_passes_test\"><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\">user_passes_test</span></code> 装饰器，当调用返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">user_passes_test</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">email_check</span><span class=\"p\">(</span><span class=\"n\">user</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">email</span><span class=\"o\">.</span><span class=\"n\">endswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;@example.com&#39;</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@user_passes_test</span><span class=\"p\">(</span><span class=\"n\">email_check</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"#django.contrib.auth.decorators.user_passes_test\" title=\"django.contrib.auth.decorators.user_passes_test\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">user_passes_test()</span></code></a> 接受一个必要的参数：一个带有:class:~django.contrib.auth.models.User 对象的调用，如果允许用户访问这个页面，则返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 。注意，<a class=\"reference internal\" href=\"#django.contrib.auth.decorators.user_passes_test\" title=\"django.contrib.auth.decorators.user_passes_test\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">user_passes_test()</span></code></a> 不会自动检查用户是否匿名。</p>\n<p><a class=\"reference internal\" href=\"#django.contrib.auth.decorators.user_passes_test\" title=\"django.contrib.auth.decorators.user_passes_test\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">user_passes_test()</span></code></a> 可以传递两个可选参数：</p>\n<dl class=\"simple\">\n<dt><code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code></dt><dd><p>允许你指定用户没有通过测试时跳转的地址。它可能是一个登录页面，如果你没指定，默认是 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> 。</p>\n</dd>\n<dt><code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code></dt><dd><p>与 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 相同。如果你想把没通过检查的用户重定向到没有 &quot;next page&quot; 的非登录页面时，把它设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> ，这样它会在 URL 中移除。</p>\n</dd>\n</dl>\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=\"nd\">@user_passes_test</span><span class=\"p\">(</span><span class=\"n\">email_check</span><span class=\"p\">,</span> <span class=\"n\">login_url</span><span class=\"o\">=</span><span class=\"s1\">&#39;/login/&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.UserPassesTestMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">UserPassesTestMixin</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.UserPassesTestMixin\"><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\">UserPassesTestMixin</span></code> 执行此操作。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.UserPassesTestMixin.test_func\">\n<span class=\"sig-name descname\"><span class=\"pre\">test_func</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.UserPassesTestMixin.test_func\"><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\">test_func()</span></code> 以提供执行的测试。此外，还可以设置 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin\" title=\"django.contrib.auth.mixins.AccessMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AccessMixin</span></code></a> 的任何参数来自定义处理未授权用户：</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.auth.mixins</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserPassesTestMixin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyView</span><span class=\"p\">(</span><span class=\"n\">UserPassesTestMixin</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_func</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">email</span><span class=\"o\">.</span><span class=\"n\">endswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;@example.com&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.UserPassesTestMixin.get_test_func\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_test_func</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.UserPassesTestMixin.get_test_func\"><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\">get_test_func()</span></code> 方法，以使 mixin 对其检查使用不同名称的函数（而不是 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.UserPassesTestMixin.test_func\" title=\"django.contrib.auth.mixins.UserPassesTestMixin.test_func\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">test_func()</span></code></a> ）。</p>\n</dd></dl>\n\n<aside class=\"admonition-stacking-userpassestestmixin admonition\">\n<p class=\"admonition-title\">集成 <code class=\"docutils literal notranslate\"><span class=\"pre\">UserPassesTestMixin</span></code></p>\n<p>由于实现了 <code class=\"docutils literal notranslate\"><span class=\"pre\">UserPassesTestMixin</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\">TestMixin1</span><span class=\"p\">(</span><span class=\"n\">UserPassesTestMixin</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_func</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">email</span><span class=\"o\">.</span><span class=\"n\">endswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;@example.com&#39;</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestMixin2</span><span class=\"p\">(</span><span class=\"n\">UserPassesTestMixin</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_func</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">username</span><span class=\"o\">.</span><span class=\"n\">startswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;django&#39;</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyView</span><span class=\"p\">(</span><span class=\"n\">TestMixin1</span><span class=\"p\">,</span> <span class=\"n\">TestMixin2</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestMixin1</span></code> 调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code> 并把结果考虑在内，<code class=\"docutils literal notranslate\"><span class=\"pre\">TestMixin1</span></code> 将不能独立运行。</p>\n</aside>\n</dd></dl>\n\n</section>\n<section id=\"the-permission-required-decorator\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">permission_required</span></code> 装饰器<a class=\"heading-anchor\" href=\"#the-permission-required-decorator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.decorators.permission_required\">\n<span class=\"sig-name descname\"><span class=\"pre\">permission_required</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">perm</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">login_url</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raise_exception</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.decorators.permission_required\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>检查用户是否拥有特定的权限是一个相对常见的任务。出于这个原因，Django 提供了一个快捷方式：<a class=\"reference internal\" href=\"#django.contrib.auth.decorators.permission_required\" title=\"django.contrib.auth.decorators.permission_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">permission_required()</span></code></a> 装饰器：</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.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">permission_required</span>\n\n<span class=\"nd\">@permission_required</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls.add_choice&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>就像 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.has_perm\" title=\"django.contrib.auth.models.User.has_perm\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_perm()</span></code></a> 方法一样，权限名称采用 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;&lt;app</span> <span class=\"pre\">label&gt;.&lt;permission</span> <span class=\"pre\">codename&gt;&quot;</span></code> 形式（比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls.polls.add_choice</span></code> 就是 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 应用程序下的模型的权限）。</p>\n<p>装饰器也可以接受可迭代权限，在这种情况下，用户必须拥有所有权限才能访问视图。</p>\n<p>注意， <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.permission_required\" title=\"django.contrib.auth.decorators.permission_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">permission_required()</span></code></a> 也可以接受可选的 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">permission_required</span>\n\n<span class=\"nd\">@permission_required</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls.add_choice&#39;</span><span class=\"p\">,</span> <span class=\"n\">login_url</span><span class=\"o\">=</span><span class=\"s1\">&#39;/loginpage/&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>和 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 装饰器一样， <code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code> 默认是:setting:settings.LOGIN_URL &lt;LOGIN_URL&gt;。</p>\n<p>如果有 <code class=\"docutils literal notranslate\"><span class=\"pre\">raise_exception</span></code> 参数，那么装饰器将引发 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 错误，提示 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/views/#http-forbidden-view\"><span class=\"std std-ref\">the 403 (HTTP Forbidden) view</span></a> 而不是跳转到登录页面。</p>\n<p>如果你想使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">raise_exception</span></code> 但也想给用户登录的机会，那需要添加 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.login_required\" title=\"django.contrib.auth.decorators.login_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">login_required()</span></code></a> 装饰器：</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.auth.decorators</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">login_required</span><span class=\"p\">,</span> <span class=\"n\">permission_required</span>\n\n<span class=\"nd\">@login_required</span>\n<span class=\"nd\">@permission_required</span><span class=\"p\">(</span><span class=\"s1\">&#39;polls.add_choice&#39;</span><span class=\"p\">,</span> <span class=\"n\">raise_exception</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>当 <a class=\"reference internal\" href=\"#django.contrib.auth.views.LoginView\" title=\"django.contrib.auth.views.LoginView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">LoginView</span></code></a> 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_authenticated_user=True</span></code> 并且已登录用户没有所有必须的权限时，这避免了重定向循环。</p>\n</dd></dl>\n\n</section>\n<section id=\"the-permissionrequiredmixin-mixin\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">PermissionRequiredMixin</span></code> Mixin<a class=\"heading-anchor\" href=\"#the-permissionrequiredmixin-mixin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>在 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/\"><span class=\"doc\">class-based views</span></a> 中应用权限检查，你可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">PermissionRequiredMixin</span></code> ：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.PermissionRequiredMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PermissionRequiredMixin</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.PermissionRequiredMixin\"><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\">permission_required</span></code> 装饰器一样，Mixin 检查用户访问的视图是否拥有全部的权限。你应该使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">permission_required</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.mixins</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">PermissionRequiredMixin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyView</span><span class=\"p\">(</span><span class=\"n\">PermissionRequiredMixin</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n    <span class=\"n\">permission_required</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;polls.add_choice&#39;</span>\n    <span class=\"c1\"># Or multiple of permissions:</span>\n    <span class=\"n\">permission_required</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;polls.view_choice&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;polls.change_choice&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>你可以设置 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin\" title=\"django.contrib.auth.mixins.AccessMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AccessMixin</span></code></a> 的任意参数来自定义处理没有权限的用户。</p>\n<p>你可能同样需要重写这些方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.PermissionRequiredMixin.get_permission_required\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_permission_required</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.PermissionRequiredMixin.get_permission_required\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回 Mixin 使用的可迭代权限的名称。默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">permission_required</span></code> 属性，如果需要可以转化为元组。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.PermissionRequiredMixin.has_permission\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_permission</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.PermissionRequiredMixin.has_permission\"><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/3.0/ref/contrib/auth/#django.contrib.auth.models.User.has_perms\" title=\"django.contrib.auth.models.User.has_perms\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_perms()</span></code></a> 的结果，其中包括返回 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.PermissionRequiredMixin.get_permission_required\" title=\"django.contrib.auth.mixins.PermissionRequiredMixin.get_permission_required\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_permission_required()</span></code></a> 的权限列表。</p>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n</section>\n<section id=\"redirecting-unauthorized-requests-in-class-based-views\">\n<h3>在基于类的视图中重定向未通过验证的请求<a class=\"heading-anchor\" href=\"#redirecting-unauthorized-requests-in-class-based-views\"><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\">AccessMixin</span></code> 被用来配置当访问被拒绝时的视图行为。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">AccessMixin</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.login_url\">\n<span class=\"sig-name descname\"><span class=\"pre\">login_url</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.login_url\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.get_login_url\" title=\"django.contrib.auth.mixins.AccessMixin.get_login_url\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_login_url()</span></code></a> 的缺省返回值。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> ，在这种情况下， <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.get_login_url\" title=\"django.contrib.auth.mixins.AccessMixin.get_login_url\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_login_url()</span></code></a> 会回退至 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.permission_denied_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">permission_denied_message</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.permission_denied_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.get_permission_denied_message\" title=\"django.contrib.auth.mixins.AccessMixin.get_permission_denied_message\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_permission_denied_message()</span></code></a> 的缺省返回值。默认是空字符串。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.redirect_field_name\">\n<span class=\"sig-name descname\"><span class=\"pre\">redirect_field_name</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.redirect_field_name\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.get_redirect_field_name\" title=\"django.contrib.auth.mixins.AccessMixin.get_redirect_field_name\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_redirect_field_name()</span></code></a> 的缺省返回值。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;next&quot;</span></code> 。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.raise_exception\">\n<span class=\"sig-name descname\"><span class=\"pre\">raise_exception</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.raise_exception\"><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\">True</span></code> ，当条件不被满足的时候会引发 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 异常。如果是 <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.auth.mixins.AccessMixin.get_login_url\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_login_url</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.get_login_url\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回当用户没有通过测试时将被重定向的网址。如果已设置，将返回 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.login_url\" title=\"django.contrib.auth.mixins.AccessMixin.login_url\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">login_url</span></code></a> ，否则返回 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> 。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.get_permission_denied_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_permission_denied_message</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.get_permission_denied_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>当 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.raise_exception\" title=\"django.contrib.auth.mixins.AccessMixin.raise_exception\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">raise_exception</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，这个方法可以控制传递给错误处理程序的错误信息，以便显示给用户。默认返回 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.permission_denied_message\" title=\"django.contrib.auth.mixins.AccessMixin.permission_denied_message\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">permission_denied_message</span></code></a> 属性。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.get_redirect_field_name\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_redirect_field_name</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.get_redirect_field_name\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回查询参数名，包含用户登录成功后重定向的 URL 。如果这个值设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> ，将不会添加查询参数。默认返回 <a class=\"reference internal\" href=\"#django.contrib.auth.mixins.AccessMixin.redirect_field_name\" title=\"django.contrib.auth.mixins.AccessMixin.redirect_field_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code></a> 属性。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.mixins.AccessMixin.handle_no_permission\">\n<span class=\"sig-name descname\"><span class=\"pre\">handle_no_permission</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.mixins.AccessMixin.handle_no_permission\"><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\">raise_exception</span></code> 的值，这个方法将会引发 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 异常或重定向用户至 <code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code> ，如果已设置，则可选地包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> 。</p>\n</dd></dl>\n\n</dd></dl>\n\n<section id=\"session-invalidation-on-password-change\">\n<span id=\"id3\"></span><h4>密码更改时会话失效<a class=\"heading-anchor\" href=\"#session-invalidation-on-password-change\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>如果 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 继承自 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 或实现了自己的 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\" title=\"django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_session_auth_hash()</span></code></a> 方法，已验证的会话将包含这个函数返回的哈希值。在 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 的情况下，这是密码字段的 HMAC 。Django 验证每个请求的会话中的哈希是否与请求期间计算的哈希相匹配。这允许用户修改密码来注销所有会话。</p>\n<p>Django 包含默认的密码修改视图，<a class=\"reference internal\" href=\"#django.contrib.auth.views.PasswordChangeView\" title=\"django.contrib.auth.views.PasswordChangeView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordChangeView</span></code></a> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_change_password</span></code> 视图在 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code></a> admin 中，将使用新密码的哈希更新会话，因此用户修改密码后不会被注销。如果你有自定义的密码修改视图，并期望有同样的行为，可以使用 <a class=\"reference internal\" href=\"#django.contrib.auth.update_session_auth_hash\" title=\"django.contrib.auth.update_session_auth_hash\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">update_session_auth_hash()</span></code></a> 函数。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.update_session_auth_hash\">\n<span class=\"sig-name descname\"><span class=\"pre\">update_session_auth_hash</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.update_session_auth_hash\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>这个函数接受当前请求和从新会话哈希派生时更新的用户对象，并会更新哈希值。它也会替换哈希值因此被盗用的会话cookie会无效。</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.contrib.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">update_session_auth_hash</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">password_change</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=\"s1\">&#39;POST&#39;</span><span class=\"p\">:</span>\n        <span class=\"n\">form</span> <span class=\"o\">=</span> <span class=\"n\">PasswordChangeForm</span><span class=\"p\">(</span><span class=\"n\">user</span><span class=\"o\">=</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"p\">,</span> <span class=\"n\">data</span><span class=\"o\">=</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">POST</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"n\">form</span><span class=\"o\">.</span><span class=\"n\">is_valid</span><span class=\"p\">():</span>\n            <span class=\"n\">form</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n            <span class=\"n\">update_session_auth_hash</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">form</span><span class=\"o\">.</span><span class=\"n\">user</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n</dd></dl>\n\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>因为 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\" title=\"django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_session_auth_hash()</span></code></a> 是基于 <a class=\"reference internal\" href=\"/zh-hans/3.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>\n</section>\n</section>\n<section id=\"module-django.contrib.auth.views\">\n<span id=\"authentication-views\"></span><span id=\"built-in-auth-views\"></span><h3>验证视图<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 提供许多可以用来处理登录、注销和密码管理的视图。这些利用了  <a class=\"reference internal\" href=\"#built-in-auth-forms\"><span class=\"std std-ref\">stock auth forms</span></a> ，但你也可以使用自己的表单。</p>\n<p>Django 没有为验证视图提供默认模板。你可以为你打算使用的视图创建自己的模板。每个视图都记录了模板上下文，详情查看 <a class=\"reference internal\" href=\"#all-authentication-views\"><span class=\"std std-ref\">所有的验证视图</span></a> 。</p>\n<section id=\"using-the-views\">\n<span id=\"id4\"></span><h4>使用视图<a class=\"heading-anchor\" href=\"#using-the-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>在项目中可以使用不同方法来实现这些视图。最简单的方法就是在 URLconf 中包含  <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.urls</span></code> 提供的 URLconf 。举例：</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\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;accounts/&#39;</span><span class=\"p\">,</span> <span class=\"n\">include</span><span class=\"p\">(</span><span class=\"s1\">&#39;django.contrib.auth.urls&#39;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>这将包含以下 URL 模式：</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\">accounts</span><span class=\"o\">/</span><span class=\"n\">login</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;login&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">logout</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;logout&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">password_change</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_change&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">password_change</span><span class=\"o\">/</span><span class=\"n\">done</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_change_done&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">password_reset</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_reset&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">password_reset</span><span class=\"o\">/</span><span class=\"n\">done</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_reset_done&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">reset</span><span class=\"o\">/&lt;</span><span class=\"n\">uidb64</span><span class=\"o\">&gt;/&lt;</span><span class=\"n\">token</span><span class=\"o\">&gt;/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_reset_confirm&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">accounts</span><span class=\"o\">/</span><span class=\"n\">reset</span><span class=\"o\">/</span><span class=\"n\">done</span><span class=\"o\">/</span> <span class=\"p\">[</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_reset_complete&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>视图提供 URL 名称以便参考。有关使用命名 URL 模式的使用详情参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/http/urls/\"><span class=\"doc\">the URL documentation</span></a> 。</p>\n<p>如果你想更好的控制 URL ，你可以在你的 URLconf 中引用特定的视图：</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.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">views</span> <span class=\"k\">as</span> <span class=\"n\">auth_views</span>\n\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;change-password/&#39;</span><span class=\"p\">,</span> <span class=\"n\">auth_views</span><span class=\"o\">.</span><span class=\"n\">PasswordChangeView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>这个视图具有更改视图行为的可选参数。例如，如果你想改变视图使用的模板名称，你可以提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> 参数。在 URLconf 中提供关键字参数，这些参数将被传递给视图。举例：</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\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span>\n        <span class=\"s1\">&#39;change-password/&#39;</span><span class=\"p\">,</span>\n        <span class=\"n\">auth_views</span><span class=\"o\">.</span><span class=\"n\">PasswordChangeView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(</span><span class=\"n\">template_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;change-password.html&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>所有视图都是基于类的，这就允许你通过子类去方便地自定义它们。</p>\n</section>\n<section id=\"all-authentication-views\">\n<span id=\"id5\"></span><h4>所有的验证视图<a class=\"heading-anchor\" href=\"#all-authentication-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>这是一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code> 提供的所有视图列表。有关实现细节可参考 <a class=\"reference internal\" href=\"#using-the-views\"><span class=\"std std-ref\">使用视图</span></a> 。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.LoginView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">LoginView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.LoginView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">login</span></code></p>\n<p>有关使用命名 URL 模式的细节可参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/http/urls/\"><span class=\"doc\">the URL documentation</span></a> 。</p>\n<p>属性：</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：用户登录的视图所使用的模板名称。默认指向 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/login.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> ： <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 字段包含的登录后跳转 URL 的参数名称。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">authentication_form</span></code> ：用于验证的调用（通常是一个表单类）。默认是 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.AuthenticationForm\" title=\"django.contrib.auth.forms.AuthenticationForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AuthenticationForm</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_authenticated_user</span></code> ：布尔值，用来控制已验证的用户访问登录页面是否被重定向，就像他们刚刚成功登录一样。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>如果你启用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_authenticated_user</span></code> ，其他网站通过重定向请求你的网站的图片文件的方式来确定他们的访客是否是你网站的已验证用户。为了避免这个 &quot;<a class=\"reference external\" href=\"https://robinlinus.github.io/socialmedia-leak/\">social media fingerprinting</a>&quot; 信息泄露，请将所有图片和 favicon 都托管在单独的域名中。</p>\n<p>启用 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_authenticated_user</span></code> 也会在使用 <a class=\"reference internal\" href=\"#django.contrib.auth.decorators.permission_required\" title=\"django.contrib.auth.decorators.permission_required\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">permission_required()</span></code></a> 装饰器的时候，导致重定向循环，除非 <code class=\"docutils literal notranslate\"><span class=\"pre\">raise_exception</span></code> 参数被使用。</p>\n</aside>\n</li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">success_url_allowed_hosts</span></code> ：除了 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.get_host\" title=\"django.http.HttpRequest.get_host\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">request.get_host()</span></code></a> 之外的主机集合，登录后能安全地重定向。默认是空集。</p></li>\n</ul>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">LoginView</span></code> 能做什么：</p>\n<ul class=\"simple\">\n<li><p>如果通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 调用，它将显示 POST 到同一 URL 地址的登录表单。稍后会详细介绍。</p></li>\n<li><p>如果用户提交的数据通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> 调用，那它将试着让用户登录。如果登录成功，那么视图将重定向到 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> 指定的 URL 。如果没有提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> ，它将重定向到 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_REDIRECT_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_REDIRECT_URL</span></code></a> （默认 <code class=\"docutils literal notranslate\"><span class=\"pre\">/accounts/profile/</span></code> ）。如果登录没有成功，它将重新显示登录表单。</p></li>\n</ul>\n<p>你需要提供登录模板，默认调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">registration/login.html</span></code> 。这个模板传递四个模板上下文变量：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form</span></code> ：一个代表 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.AuthenticationForm\" title=\"django.contrib.auth.forms.AuthenticationForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AuthenticationForm</span></code></a> 的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/forms/api/#django.forms.Form\" title=\"django.forms.Form\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Form</span></code></a> 对象。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> ：登录成功后跳转的网址。这可能包含查询字段。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">site</span></code> ：根据 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-SITE_ID\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SITE_ID</span></code></a> 设置的当前站点。如果你还没有安装站点框架，会将其设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/sites/#django.contrib.sites.requests.RequestSite\" title=\"django.contrib.sites.requests.RequestSite\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestSite</span></code></a> 实例，该实例从当前 <a class=\"reference internal\" href=\"/zh-hans/3.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> 中派生出站点名和域名。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">site_name</span></code> ：<code class=\"docutils literal notranslate\"><span class=\"pre\">site.name</span></code> 的别名。如果你还没有按照站点框架，它将设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.META\" title=\"django.http.HttpRequest.META\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.META['SERVER_NAME']</span></code></a> 的值。更多关于站点信息，请参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/sites/\"><span class=\"doc\">The &quot;sites&quot; framework</span></a> 。</p></li>\n</ul>\n<p>如果你不愿意调用模板 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/login.html</span></code> ，你可以通过附加参数的形式传递 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> 参数给你的 URLconf 中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_view</span></code> 方法。比如，这行 URLconf 将使用 <code class=\"file docutils literal notranslate\"><span class=\"pre\">myapp/login.html</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\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;accounts/login/&#39;</span><span class=\"p\">,</span> <span class=\"n\">auth_views</span><span class=\"o\">.</span><span class=\"n\">LoginView</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(</span><span class=\"n\">template_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;myapp/login.html&#39;</span><span class=\"p\">)),</span>\n</code></pre></div>\n<p>你也可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> 指定 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 字段的名称，这个字段包含登陆后跳转的 URL 地址。默认情况下，这个字段为 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> 。</p>\n<p>下面是一个简单的 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/login.html</span></code> 模板。它假设你有 <code class=\"file docutils literal notranslate\"><span class=\"pre\">base.html</span></code> 模板，并且已经定义了 <code class=\"docutils literal notranslate\"><span class=\"pre\">content</span></code> 块：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">&quot;base.html&quot;</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">content</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">form.errors</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>Your username and password didn&#39;t match. Please try again.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">next</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">user.is_authenticated</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>Your account doesn&#39;t have access to this page. To proceed,\n    please login with an account that has access.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>Please login to see this page.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">form</span> <span class=\"na\">method</span><span class=\"o\">=</span><span class=\"s\">&quot;post&quot;</span> <span class=\"na\">action</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;login&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">csrf_token</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">table</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.username.label_tag</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.username</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.password.label_tag</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">form.password</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">td</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">tr</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">table</span><span class=\"p\">&gt;</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;submit&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;login&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">input</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;hidden&quot;</span> <span class=\"na\">name</span><span class=\"o\">=</span><span class=\"s\">&quot;next&quot;</span> <span class=\"na\">value</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">next</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">form</span><span class=\"p\">&gt;</span>\n\n<span class=\"c\">{# Assumes you setup the password_reset view in your URLconf #}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;password_reset&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Lost password?<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>如果你具有自定义身份验证（查看 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/customizing/\"><span class=\"doc\">Customizing Authentication</span></a> ），可以通过设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">authentication_form</span></code> 属性来使用自定义的验证码模板。此表单必须在它的 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__()</span></code> 方法中接受 <code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> 关键字参数，并且提供一个返回已验证用户对象的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_user()</span></code> 方法（这个方法只会在表单成功验证后调用）。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.LogoutView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">LogoutView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.LogoutView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>注销用户</p>\n<p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">logout</span></code></p>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">next_page</span></code> ：注销后将要跳转的 URL 。默认是 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGOUT_REDIRECT_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGOUT_REDIRECT_URL</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：用户注销后显示的模板地址。默认是 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/logged_out.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> ：注销后包含重定向 URL 的 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 字段名称。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> 。如果传递给定的 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 参数，将会覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">next_page</span></code> URL。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">success_url_allowed_hosts</span></code> ：除了 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.get_host\" title=\"django.http.HttpRequest.get_host\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">request.get_host()</span></code></a> 之外的主机集合，在注销后可以安全地重定向。默认是空集。</p></li>\n</ul>\n<p><strong>Template context:</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">title</span></code> ：字符串 &quot;已注销&quot;，已本地化。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">site</span></code> ：根据 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-SITE_ID\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SITE_ID</span></code></a> 设置的当前站点。如果你还没有安装站点框架，会将其设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/sites/#django.contrib.sites.requests.RequestSite\" title=\"django.contrib.sites.requests.RequestSite\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestSite</span></code></a> 实例，该实例从当前 <a class=\"reference internal\" href=\"/zh-hans/3.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> 中派生出站点名和域名。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">site_name</span></code> ：<code class=\"docutils literal notranslate\"><span class=\"pre\">site.name</span></code> 的别名。如果你还没有按照站点框架，它将设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.META\" title=\"django.http.HttpRequest.META\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.META['SERVER_NAME']</span></code></a> 的值。更多关于站点信息，请参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/sites/\"><span class=\"doc\">The &quot;sites&quot; framework</span></a> 。</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.logout_then_login\">\n<span class=\"sig-name descname\"><span class=\"pre\">logout_then_login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">request</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">login_url</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.auth.views.logout_then_login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>用户注销，然后重定向到登录页面。</p>\n<p><strong>URL name:</strong> 没有提供默认的 URL</p>\n<p>可选参数：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code> ：要重定向到登录页面的 URL 。如果没有提供，默认是 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> 。</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordChangeView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordChangeView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordChangeView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_change</span></code></p>\n<p>允许用户修改密码。</p>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：用于显示密码修改表单的模板全称。如果没提供则默认 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_change_form.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">success_url</span></code> ：密码修改成功后跳转的 URL 。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">'password_change_done'</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ：一个自定义修改密码的表单，此表单必须接收 <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> 关键字参数。表单负责实际修改用户密码。默认是 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.PasswordChangeForm\" title=\"django.contrib.auth.forms.PasswordChangeForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordChangeForm</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n</ul>\n<p><strong>Template context:</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form</span></code> ：密码修改表单（参考上面的 <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ）</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordChangeDoneView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordChangeDoneView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordChangeDoneView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_change_done</span></code></p>\n<p>用户修改密码之后显示的页面。</p>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：所使用模板的全称。如果没有提供，则默认 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_change_done.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordResetView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordResetView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordResetView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_reset</span></code></p>\n<p>允许用户通过生成的一次性链接来重置密码，并把一次性链接发到用户注册邮箱中。</p>\n<p>如果邮箱地址并不存在，视图不会发送邮件，但用户也不会受到任何错误信息。这是为了防止信息泄露给潜在的攻击者。如果你想提供错误信息，你可以成为继承 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.PasswordResetForm\" title=\"django.contrib.auth.forms.PasswordResetForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordResetForm</span></code></a> ，并使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> 属性。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>注意，发送邮件需要花费额外时间，因此，由于对现有电子邮件地址的重置请求的持续时间与对不存在的电子邮件地址的重置请求的持续时间不同，你可能容易受到电子邮件地址枚举定时攻击。为了降低开销，你可以使用第三方插件来允许异步发送邮件，例如 <a class=\"reference external\" href=\"https://pypi.org/project/django-mailer/\">django-mailer</a></p>\n</aside>\n<p>不可使用密码的用户 （查看 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password\" title=\"django.contrib.auth.models.User.set_unusable_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_unusable_password()</span></code></a> ）不能请求重置密码，以防止在使用类似 LDAP 等外部验证源时滥用。注意，它们将无法收到错误信息，因为这将暴露用户账号是否存在，并且也不会发送邮件。</p>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：用来显示密码重置表单的模板全称。如果没提供，则默认 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_form.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ：用于获取用户的重置密码的电子邮件的表单。默认是 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.PasswordResetForm\" title=\"django.contrib.auth.forms.PasswordResetForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordResetForm</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">email_template_name</span></code> ：用来生成重置密码链接的电子邮件模板。如果没有提供，默认是 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_email.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">subject_template_name</span></code> ：重置密码电子邮件主题的模板全称。如果没有提供，则是 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_subject.txt</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">token_generator</span></code> ：检测一次性链接的类实例。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">default_token_generator</span></code> ，这是 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.tokens.PasswordResetTokenGenerator</span></code> 的一个实例。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">success_url</span></code>: 密码重置请求成功后跳转的 URL 。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">'password_reset_done'</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">from_email</span></code> ：合法邮件地址。默认情况下，Django 使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-DEFAULT_FROM_EMAIL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DEFAULT_FROM_EMAIL</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">html_email_template_name</span></code> ：用来生成带有密码重置链接的 <code class=\"docutils literal notranslate\"><span class=\"pre\">text/html</span></code> 多用途电子邮件。默认情况下，HTML 单子邮件不会被发送。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_email_context</span></code>: 在邮件模板提供上下文数据字典。它被用来覆盖下面列出的默认模板上下文值，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">domain</span></code>。</p></li>\n</ul>\n<p><strong>Template context:</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form</span></code> ：重置用户密码的表单（可参考上面的 <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ）。</p></li>\n</ul>\n<p><strong>电子邮件模板上下文:</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">email</span></code> ：<code class=\"docutils literal notranslate\"><span class=\"pre\">user.email</span></code> 的别名。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> ：根据电子邮件表单字段指定的当前用户。只有活动用户才可以重置密码（ <code class=\"docutils literal notranslate\"><span class=\"pre\">User.is_active</span> <span class=\"pre\">为</span> <span class=\"pre\">True</span></code> ）。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">site_name</span></code> ：<code class=\"docutils literal notranslate\"><span class=\"pre\">site.name</span></code> 的别名。如果你还没有按照站点框架，它将设置为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/request-response/#django.http.HttpRequest.META\" title=\"django.http.HttpRequest.META\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">request.META['SERVER_NAME']</span></code></a> 的值。更多关于站点信息，请参考 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/sites/\"><span class=\"doc\">The &quot;sites&quot; framework</span></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">domain</span></code> ：<code class=\"docutils literal notranslate\"><span class=\"pre\">site.domain</span></code> 的别名。如果你还没有安装网站框架，它会被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">request.get_host()</span></code> 的值。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">protocol</span></code> ：http 或 https</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">uid</span></code> ：使用 Base64 编码过的用户主键。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">token</span></code> ：检测重置密码链接是否有效的 Token 。</p></li>\n</ul>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">registration/password_reset_email.html</span></code> 例子（电子邮件内容模板）</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code>Someone asked for password reset for email <span class=\"cp\">{{</span> <span class=\"nv\">email</span> <span class=\"cp\">}}</span>. Follow the link below:\n<span class=\"cp\">{{</span> <span class=\"nv\">protocol</span><span class=\"cp\">}}</span>://<span class=\"cp\">{{</span> <span class=\"nv\">domain</span> <span class=\"cp\">}}{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;password_reset_confirm&#39;</span> <span class=\"nv\">uidb64</span><span class=\"o\">=</span><span class=\"nv\">uid</span> <span class=\"nv\">token</span><span class=\"o\">=</span><span class=\"nv\">token</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>相同的模板上下文用于主题模板。主题必须是单行纯文本字符串。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordResetDoneView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordResetDoneView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordResetDoneView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_reset_done</span></code></p>\n<p>发送重置密码邮件后显示的页面。如果 <a class=\"reference internal\" href=\"#django.contrib.auth.views.PasswordResetView\" title=\"django.contrib.auth.views.PasswordResetView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordResetView</span></code></a> 没有明确设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">success_url</span></code> ，那么默认将该视图调用。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>如果提供的电子邮件地址在系统内并不存在，那么用户可能是非活动用户，或者密码不可被更改。用户仍然会重定向到这个视图，但不会发送邮件。</p>\n</aside>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：被使用模板的全称。如果没有提供，则默认是 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_done.html</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordResetConfirmView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordResetConfirmView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordResetConfirmView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_reset_confirm</span></code></p>\n<p>提供输入新密码的表单。</p>\n<p>URL 的关键参数</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">uidb64</span></code> ：被Base64编码过的用户 id。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">token</span></code> ：检查密码是否有效的 Token。</p></li>\n</ul>\n<p>属性：</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：用于显示确认密码视图的模板全称。默认值是 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_confirm.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">token_generator</span></code> ：检查密码的类实例。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">default_token_generator</span></code>，它是 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.tokens.PasswordResetTokenGenerator</span></code> 的实例。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">post_reset_login</span></code> ：布尔值，用来标示用户成功重置密码后是否会被自动验证。默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">post_reset_login_backend</span></code> ：验证后端的路径，用于当 <code class=\"docutils literal notranslate\"><span class=\"pre\">post_reset_login</span></code> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时验证用户使用。当拥有多个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 设置时才会用到。默认为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ：用来设置密码的表单。默认是 <a class=\"reference internal\" href=\"#django.contrib.auth.forms.SetPasswordForm\" title=\"django.contrib.auth.forms.SetPasswordForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SetPasswordForm</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">success_url</span></code> ：重置密码完成后跳转的 URL 。默认 <code class=\"docutils literal notranslate\"><span class=\"pre\">'password_reset_complete'</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">reset_url_token</span></code>: Token 参数为密码重置链接的组成部分。默认 <code class=\"docutils literal notranslate\"><span class=\"pre\">'set-password'</span></code> 。</p>\n<aside class=\"version-note version-changed\" data-version=\"3.0\">\n<p class=\"version-note-title\">Changed in Django 3.0</p><p>已添加 <code class=\"docutils literal notranslate\"><span class=\"pre\">reset_url_token</span></code> 类属性。</p>\n</aside>\n</li>\n</ul>\n<p><strong>Template context:</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">form</span></code> ：用来设置用户新密码的表单（查看上面的 <code class=\"docutils literal notranslate\"><span class=\"pre\">form_class</span></code> ）。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">validlink</span></code> ：布尔值，如果链接（<code class=\"docutils literal notranslate\"><span class=\"pre\">uidb64</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">token</span></code> 的组合）有效且合法，则返回 True 。</p></li>\n</ul>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.PasswordResetCompleteView\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordResetCompleteView</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.PasswordResetCompleteView\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><strong>URL name:</strong> <code class=\"docutils literal notranslate\"><span class=\"pre\">password_reset_complete</span></code></p>\n<p>当密码已经被修改成功后通知用户的视图。</p>\n<p>属性：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ：显示视图的模板全称。默认 <code class=\"file docutils literal notranslate\"><span class=\"pre\">registration/password_reset_complete.html</span></code> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">extra_context</span></code> ：上下文数据字典，通过模板添加到默认上下文数据中。</p></li>\n</ul>\n</dd></dl>\n\n</section>\n</section>\n<section id=\"helper-functions\">\n<h3>辅助函数<a class=\"heading-anchor\" href=\"#helper-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.views.redirect_to_login\">\n<span class=\"sig-name descname\"><span class=\"pre\">redirect_to_login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">next</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">login_url</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">redirect_field_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'next'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.views.redirect_to_login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>重定向到登录页面，登陆成功后跳转到其他 URL 。</p>\n<p><strong>必要参数</strong></p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> ：成功登陆后跳转的 URL。</p></li>\n</ul>\n<p>可选参数：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">login_url</span></code> ：要重定向到登录页面的 URL 。如果没有提供，默认是 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">settings.LOGIN_URL</span></code></a> 。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_field_name</span></code> ：注销后跳转的 URL 所包含的 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 字段名称。如果已传递给定的 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 参数，则覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">next</span></code> 。</p></li>\n</ul>\n</dd></dl>\n\n</section>\n<section id=\"module-django.contrib.auth.forms\">\n<span id=\"built-in-forms\"></span><span id=\"built-in-auth-forms\"></span><h3>内置表单<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.forms\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你不想使用内置视图，但希望不必为此功能编写表单，验证系统提供很多在 <a class=\"reference internal\" href=\"#module-django.contrib.auth.forms\" title=\"django.contrib.auth.forms\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.forms</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/3.0/topics/auth/customizing/#custom-users-and-the-built-in-auth-forms\"><span class=\"std std-ref\">custom user model ` ，它可能需要为验证系统定义你自己的表单。如需了解更多信息，参考文档 :ref:`using the built-in authentication forms with custom user models</span></a> 。</p>\n</aside>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.AdminPasswordChangeForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">AdminPasswordChangeForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.AdminPasswordChangeForm\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在管理界面修改用户密码所使用的表单。</p>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> 作为第一个参数。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.AuthenticationForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">AuthenticationForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.AuthenticationForm\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>用户登录的表单。</p>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> 作为第一个参数，该参数存储在表单实例上，供子类使用。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.AuthenticationForm.confirm_login_allowed\">\n<span class=\"sig-name descname\"><span class=\"pre\">confirm_login_allowed</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.AuthenticationForm.confirm_login_allowed\"><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\">AuthenticationForm</span></code> 拒绝  <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active</span></code> 标识为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 的用户。你可以通过自定义策略来覆盖这个行为来决定哪个用户可以登录。通过``AuthenticationForm`` 子类的自定义表单来执行这个操作，并覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">confirm_login_allowed()</span></code> 方法。如果给定的用户无法登录，这个方法应该引发 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code></a> 错误。</p>\n<p>举例，允许所有用户登录而不管 &quot;active&quot; 状态：</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.auth.forms</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AuthenticationForm</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthenticationFormWithInactiveUsersOkay</span><span class=\"p\">(</span><span class=\"n\">AuthenticationForm</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">confirm_login_allowed</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"p\">):</span>\n        <span class=\"k\">pass</span>\n</code></pre></div>\n<p>（在这个例子中，你将需要使用一个允许非活动用户的验证后端，比如 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersModelBackend\" title=\"django.contrib.auth.backends.AllowAllUsersModelBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AllowAllUsersModelBackend</span></code></a> 。）</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PickyAuthenticationForm</span><span class=\"p\">(</span><span class=\"n\">AuthenticationForm</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">confirm_login_allowed</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_active</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">ValidationError</span><span class=\"p\">(</span>\n                <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;This account is inactive.&quot;</span><span class=\"p\">),</span>\n                <span class=\"n\">code</span><span class=\"o\">=</span><span class=\"s1\">&#39;inactive&#39;</span><span class=\"p\">,</span>\n            <span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">username</span><span class=\"o\">.</span><span class=\"n\">startswith</span><span class=\"p\">(</span><span class=\"s1\">&#39;b&#39;</span><span class=\"p\">):</span>\n            <span class=\"k\">raise</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">ValidationError</span><span class=\"p\">(</span>\n                <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;Sorry, accounts starting with &#39;b&#39; aren&#39;t welcome here.&quot;</span><span class=\"p\">),</span>\n                <span class=\"n\">code</span><span class=\"o\">=</span><span class=\"s1\">&#39;no_b_users&#39;</span><span class=\"p\">,</span>\n            <span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.PasswordChangeForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordChangeForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.PasswordChangeForm\"><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 class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.PasswordResetForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">PasswordResetForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.PasswordResetForm\"><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.auth.forms.PasswordResetForm.send_mail\">\n<span class=\"sig-name descname\"><span class=\"pre\">send_mail</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">subject_template_name</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">email_template_name</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">context</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">from_email</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">to_email</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html_email_template_name</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.auth.forms.PasswordResetForm.send_mail\"><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\">EmailMultiAlternatives</span></code>。可以重写自定义邮件发送给用户的方式。</p>\n<dl class=\"field-list simple\">\n<dt class=\"field-odd\">参数<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>subject_template_name</strong> -- 主题模板</p></li>\n<li><p><strong>email_template_name</strong> -- 邮件主体模板</p></li>\n<li><p><strong>context</strong> -- 上下文传递至 <code class=\"docutils literal notranslate\"><span class=\"pre\">subject_template</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">email_template</span></code>, 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">html_email_template</span></code> （如果它非空）。</p></li>\n<li><p><strong>from_email</strong> -- 发送方的邮箱地址。</p></li>\n<li><p><strong>to_email</strong> -- 接收方的邮箱地址。</p></li>\n<li><p><strong>html_email_template_name</strong> -- HTML 正文模板；默认是 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，在这种情况下发送纯文本邮件。</p></li>\n</ul>\n</dd>\n</dl>\n<p>默认情况下，<code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> 使用 <a class=\"reference internal\" href=\"#django.contrib.auth.views.PasswordResetView\" title=\"django.contrib.auth.views.PasswordResetView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordResetView</span></code></a> 传递给其电子邮件上下文的相同变量填充上下文。</p>\n</dd></dl>\n\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.SetPasswordForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">SetPasswordForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.SetPasswordForm\"><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 class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.UserChangeForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">UserChangeForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.UserChangeForm\"><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 class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.forms.UserCreationForm\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">UserCreationForm</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.forms.UserCreationForm\"><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/3.0/topics/forms/modelforms/#django.forms.ModelForm\" title=\"django.forms.ModelForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelForm</span></code></a> 。</p>\n<p>它有三个字段： <code class=\"docutils literal notranslate\"><span class=\"pre\">username</span></code> （来自用户模型），<code class=\"docutils literal notranslate\"><span class=\"pre\">password1</span></code> ，和 <code class=\"docutils literal notranslate\"><span class=\"pre\">password2</span></code> 。它检查 <code class=\"docutils literal notranslate\"><span class=\"pre\">password1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">password2</span></code> 是否匹配，使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/auth/passwords/#django.contrib.auth.password_validation.validate_password\" title=\"django.contrib.auth.password_validation.validate_password\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">validate_password()</span></code></a> 验证密码，并且使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password\" title=\"django.contrib.auth.models.User.set_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_password()</span></code></a> 来设置用户密码。</p>\n</dd></dl>\n\n</section>\n<section id=\"authentication-data-in-templates\">\n<h3>模板内验证数据<a class=\"heading-anchor\" href=\"#authentication-data-in-templates\"><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/3.0/ref/templates/api/#django.template.RequestContext\" title=\"django.template.RequestContext\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestContext</span></code></a> 时，当前已登录用户和他们的权限在 :doc:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>template context ` 中是可用的。</p>\n<aside class=\"admonition-technicality admonition\">\n<p class=\"admonition-title\">技术细节</p>\n<p>从技术上讲，如果你使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/templates/api/#django.template.RequestContext\" title=\"django.template.RequestContext\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestContext</span></code></a> ，这些变量只在模板上下文中可用，并且已启用 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.contrib.auth.context_processors.auth'</span></code> 处理机。它默认产生配置文件。了解更多，可以查看 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/templates/api/#subclassing-context-requestcontext\"><span class=\"std std-ref\">RequestContext docs</span></a> 。</p>\n</aside>\n<section id=\"users\">\n<h4>用户<a class=\"heading-anchor\" href=\"#users\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当渲染模板 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/templates/api/#django.template.RequestContext\" title=\"django.template.RequestContext\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestContext</span></code></a> ，当前登录用户（<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 实例或 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser\" title=\"django.contrib.auth.models.AnonymousUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AnonymousUser</span></code></a> 实例）被保存在模板变量 <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">user</span> <span class=\"pre\">}}</span></code> 中：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">user.is_authenticated</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>Welcome, <span class=\"cp\">{{</span> <span class=\"nv\">user.username</span> <span class=\"cp\">}}</span>. Thanks for logging in.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>Welcome, new user. Please log in.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>如果没有使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">RequestContext</span></code> ，那么这个模板上下文变量将不可用。</p>\n</section>\n<section id=\"permissions\">\n<h4>权限<a class=\"heading-anchor\" href=\"#permissions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>当前登录用户的权限保存在模板变量 <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">perms</span> <span class=\"pre\">}}</span></code> 中。这是 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.context_processors.PermWrapper</span></code> 的一个实例，它是一个对模板友好的权限代理。</p>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">{{</span> <span class=\"pre\">perms</span> <span class=\"pre\">}}</span></code> 的单属性查找作为布尔值为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.has_module_perms\" title=\"django.contrib.auth.models.User.has_module_perms\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">User.has_module_perms()</span></code></a> 的代理。比如，检测登录用户是否拥有一些权限：</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=\"p\">{</span><span class=\"o\">%</span> <span class=\"k\">if</span> <span class=\"n\">perms</span><span class=\"o\">.</span><span class=\"n\">foo</span> <span class=\"o\">%</span><span class=\"p\">}</span>\n</code></pre></div>\n<p>将两层属性查找作为布尔值是 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/contrib/auth/#django.contrib.auth.models.User.has_perm\" title=\"django.contrib.auth.models.User.has_perm\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">User.has_perm()</span></code></a> 的代理。比如，检测登录用户是否拥有  <code class=\"docutils literal notranslate\"><span class=\"pre\">foo.add_vote</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=\"p\">{</span><span class=\"o\">%</span> <span class=\"k\">if</span> <span class=\"n\">perms</span><span class=\"o\">.</span><span class=\"n\">foo</span><span class=\"o\">.</span><span class=\"n\">add_vote</span> <span class=\"o\">%</span><span class=\"p\">}</span>\n</code></pre></div>\n<p>以下是一个在模板中检查权限的更完整的示例：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">perms.foo</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>You have permission to do something in the foo app.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">perms.foo.add_vote</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>You can vote!<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">perms.foo.add_driving</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>You can drive!<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>You don&#39;t have permission to do anything in the foo app.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>也可以通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">if</span> <span class=\"pre\">in</span> <span class=\"pre\">%}</span></code> 语句来查找权限。比如：</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"s1\">&#39;foo&#39;</span> <span class=\"k\">in</span> <span class=\"nv\">perms</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"s1\">&#39;foo.add_vote&#39;</span> <span class=\"k\">in</span> <span class=\"nv\">perms</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>In lookup works, too.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n</section>\n</section>\n<section id=\"managing-users-in-the-admin\">\n<span id=\"auth-admin\"></span><h2>在管理界面中管理用户<a class=\"heading-anchor\" href=\"#managing-users-in-the-admin\"><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.contrib.admin</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code>，管理后台提供了方便的方法来查看和管理用户、组和权限。用户可以增加和删除任何 Django 模型。可以创建组，也可以为用户和组分配权限。用户操作模型的日志也会在管理后台中保存和显示。</p>\n<section id=\"id6\">\n<h3>创建用户<a class=\"heading-anchor\" href=\"#id6\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以在管理后台主页的 “认证和权限” 部分看到 “用户” 链接。“增加用户”的管理界面和其他标准的管理后台不同的是：你需要先输入一个新用户名和新密码，然后才能编辑新用户的剩余字段。</p>\n<p>注意：如果你希望某个用户账号可以在 Django 管理后台创建用户，你将需要给用户“创建”和“修改”权限。如果账号只有“创建”权限但没有“修改”权限，那么这个账号将不能增加用户。为什么？因为你有权限添加用户，那么你就拥有添加超级管理员的权利，而超级管理员就可以修改其他用户。因此，Django 需要添加和修改权限作为安全措施。</p>\n<p>要考虑如何允许用户去管理权限。如果你允许普通管理员编辑用户，这和给他们超级管理员权限一样。因为他们有权利提升用户权限，包括他们自己。</p>\n</section>\n<section id=\"id7\">\n<h3>更改密码<a class=\"heading-anchor\" href=\"#id7\"><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/3.0/topics/auth/passwords/\"><span class=\"doc\">password storage details</span></a> 。这个信息中包含一个指向密码修改表单的链接，该表单允许管理员修改用户密码。</p>\n</section>\n</section>","rootId":"using-the-django-authentication-system","toc":[{"title":"User 对象","anchor":"user-objects","children":[{"title":"创建用户","anchor":"creating-users","children":[]},{"title":"创建超级用户","anchor":"creating-superusers","children":[]},{"title":"更改密码","anchor":"changing-passwords","children":[]},{"title":"验证用户","anchor":"authenticating-users","children":[]}]},{"title":"权限和认证","anchor":"permissions-and-authorization","children":[{"title":"默认权限","anchor":"default-permissions","children":[]},{"title":"组","anchor":"groups","children":[]},{"title":"以编程方式创建权限","anchor":"programmatically-creating-permissions","children":[]},{"title":"权限缓存","anchor":"permission-caching","children":[]},{"title":"代理模型","anchor":"proxy-models","children":[]}]},{"title":"Web 请求的认证","anchor":"authentication-in-web-requests","children":[{"title":"用户如何登陆","anchor":"how-to-log-a-user-in","children":[{"title":"选择验证后端","anchor":"selecting-the-authentication-backend","children":[]}]},{"title":"用户如何登出","anchor":"how-to-log-a-user-out","children":[]},{"title":"限制对未登录用户的访问","anchor":"limiting-access-to-logged-in-users","children":[{"title":"原始方式","anchor":"the-raw-way","children":[]},{"title":"login_required 装饰器","anchor":"the-login-required-decorator","children":[]},{"title":"LoginRequired Mixin","anchor":"the-loginrequired-mixin","children":[]},{"title":"限制对通过测试的登录用户的访问","anchor":"limiting-access-to-logged-in-users-that-pass-a-test","children":[]},{"title":"permission_required 装饰器","anchor":"the-permission-required-decorator","children":[]},{"title":"PermissionRequiredMixin Mixin","anchor":"the-permissionrequiredmixin-mixin","children":[]}]},{"title":"在基于类的视图中重定向未通过验证的请求","anchor":"redirecting-unauthorized-requests-in-class-based-views","children":[{"title":"密码更改时会话失效","anchor":"session-invalidation-on-password-change","children":[]}]},{"title":"验证视图","anchor":"module-django.contrib.auth.views","children":[{"title":"使用视图","anchor":"using-the-views","children":[]},{"title":"所有的验证视图","anchor":"all-authentication-views","children":[]}]},{"title":"辅助函数","anchor":"helper-functions","children":[]},{"title":"内置表单","anchor":"module-django.contrib.auth.forms","children":[]},{"title":"模板内验证数据","anchor":"authentication-data-in-templates","children":[{"title":"用户","anchor":"users","children":[]},{"title":"权限","anchor":"permissions","children":[]}]}]},{"title":"在管理界面中管理用户","anchor":"managing-users-in-the-admin","children":[{"title":"创建用户","anchor":"id6","children":[]},{"title":"更改密码","anchor":"id7","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/3.0/topics/"},{"docname":"topics/auth/index","title":"Django中的用户认证","url":"/zh-hans/3.0/topics/auth/"}],"prev":{"docname":"topics/auth/index","title":"Django中的用户认证","url":"/zh-hans/3.0/topics/auth/"},"next":{"docname":"topics/auth/passwords","title":"Django中的密码管理","url":"/zh-hans/3.0/topics/auth/passwords/"},"formats":{"html":"/zh-hans/3.0/topics/auth/default/","markdown":"/zh-hans/3.0/topics/auth/default.md","json":"/zh-hans/3.0/topics/auth/default.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/auth/default.txt","official":"https://docs.djangoproject.com/zh-hans/3.0/topics/auth/default/","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","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}