{"title":"与基于类的视图一起使用 mixins","version":"3.0","locale":"zh-hans","docname":"topics/class-based-views/mixins","url":"/zh-hans/3.0/topics/class-based-views/mixins/","canonical":"https://djangodocs.dev/zh-hans/3.0/topics/class-based-views/mixins/","summary":"Caution 这是一个高级主题。浏览这些技术之前，建议先看 Django's class-based views 的知识。 Django 的内建的基于类的视图提供很多函数特性，但有些你可能想单独使用。比如，你可能想编写一个视图用来呈现一个模板来进行 HTTP 响应，但你不能使用 TemplateView ；或许你只需要在…","html":"<h1>与基于类的视图一起使用 mixins<a class=\"heading-anchor\" href=\"#using-mixins-with-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"admonition admonition-caution\" role=\"note\">\n<p class=\"admonition-title\">Caution</p>\n<p>这是一个高级主题。浏览这些技术之前，建议先看 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/class-based-views/\"><span class=\"doc\">Django's class-based views</span></a> 的知识。</p>\n</aside>\n<p>Django 的内建的基于类的视图提供很多函数特性，但有些你可能想单独使用。比如，你可能想编写一个视图用来呈现一个模板来进行 HTTP 响应，但你不能使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/base/#django.views.generic.base.TemplateView\" title=\"django.views.generic.base.TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> ；或许你只需要在 <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> 上渲染模板，用 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 来处理其他所有事情。当你直接使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> 时，这将容易导致重复代码。</p>\n<p>因为这个原因，Django 也提供了很多提供分离特性的mixins。比如，模板渲染被封装在 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a> 里。Django 参考文档包含所有有关 mixins 的资料（ <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins/\"><span class=\"doc\">full documentation of all the mixins</span></a>）。</p>\n<section id=\"context-and-template-responses\">\n<h2>上下文和模板响应<a class=\"heading-anchor\" href=\"#context-and-template-responses\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>提供了两个重要的 mixins，有助于提供一致的界面，以便在基于类的视图中使用。</p>\n<dl>\n<dt><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a></dt><dd><p>每一个返回 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a>  的内置视图将调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code> 提供的  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a> 方法。大部分时间里会被你调用（比如，它通过 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/base/#django.views.generic.base.TemplateView\" title=\"django.views.generic.base.TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a>) 共同实现的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> 方法调用）；类似的，它不太可能需要你去覆盖它，尽管如果你希望响应返回一些没有被 Django 模板渲染的东西，那么你就会想要这么做。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code> 本身调用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names\" title=\"django.views.generic.base.TemplateResponseMixin.get_template_names\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code></a> ，它默认只是检查基于类的视图上的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.template_name\" title=\"django.views.generic.base.TemplateResponseMixin.template_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name</span></code></a> 。当处理真实对象时，两个其他 mixins (<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectTemplateResponseMixin</span></code></a>) 覆盖它来提供更多灵活默认值。</p>\n</dd>\n<dt><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin\" title=\"django.views.generic.base.ContextMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ContextMixin</span></code></a></dt><dd><p>每个需要上下文数据的内建视图，比如为了渲染一个模板（在上面包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code> ），应该调用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a> 传递任何它们想要确定的数据当做关键参数。<code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> 返回一个字典；在 <code class=\"docutils literal notranslate\"><span class=\"pre\">ContextMixin</span></code> 里它只返回它的关键参数，但它通常覆盖此项以添加更多成员到字典中。你也可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.extra_context\" title=\"django.views.generic.base.ContextMixin.extra_context\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">extra_context</span></code></a> 属性。</p>\n</dd>\n</dl>\n</section>\n<section id=\"building-up-django-s-generic-class-based-views\">\n<h2>构造 Django 基于类的通用视图<a class=\"heading-anchor\" href=\"#building-up-django-s-generic-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>让我们看 Django 的两个基于类的通用视图如何由 mixins 构建，提供分离功能的。我们考虑 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> ，它渲染一个对象的详情视图，还有 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> ，它渲染一个对象列表，通常来自查询集，并且可以分页。这里将介绍四个 mixins ，它们在使用单个 Django 对象或多个对象时，提供常用功能。</p>\n<p>mixins 也包含在通用编辑视图( <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView\" title=\"django.views.generic.edit.FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> 、指定模型视图 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView\" title=\"django.views.generic.edit.CreateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CreateView</span></code></a> 、 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView\" title=\"django.views.generic.edit.UpdateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UpdateView</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView\" title=\"django.views.generic.edit.DeleteView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DeleteView</span></code></a> ) 里，基于日期的通用视图。这些包括在 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins/\"><span class=\"doc\">mixin reference documentation</span></a> 。</p>\n<section id=\"detailview-working-with-a-single-django-object\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code> ：使用单个 Django 对象<a class=\"heading-anchor\" href=\"#detailview-working-with-a-single-django-object\"><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/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> ，并将该对象作为上下文。</p>\n<p>为了获取对象，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 依靠于 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> ，它提供一个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a> 方法，该方法根据请求的 URL 来计算对象（它寻找 URLconf 中的声明的 <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">slug</span></code> 关键参数，并从视图上的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.model\" title=\"django.views.generic.detail.SingleObjectMixin.model\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">model</span></code></a>  属性查找对象，或者如果提供了 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.queryset\" title=\"django.views.generic.detail.SingleObjectMixin.queryset\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">queryset</span></code></a>  属性，将使用这个属性）。<code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> 也覆盖了 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a> ，它被用于所有 Django 内置的基于类的视图，为模板渲染提供上下文数据。</p>\n<p>然后创建一个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> ，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> ，它用来扩展:class:~django.views.generic.base.TemplateResponseMixin，覆盖了 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names\" title=\"django.views.generic.base.TemplateResponseMixin.get_template_names\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code></a> 如上所述。它实际上提供了一个相当复杂的选项，但大部分人使用的是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app_label&gt;/&lt;model_name&gt;_detail.html</span></code> 。可以通过子类上的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name_suffix</span></code></a> 设置为其他内容来改变 <code class=\"docutils literal notranslate\"><span class=\"pre\">_detail</span></code> 部分。(比如，<a class=\"reference internal\" href=\"/zh-hans/3.0/topics/class-based-views/generic-editing/\"><span class=\"doc\">generic edit views</span></a> 使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">_form</span></code> 来创建和更新视图，用 <code class=\"docutils literal notranslate\"><span class=\"pre\">_confirm_delete</span></code> 来删除视图。)</p>\n</section>\n<section id=\"listview-working-with-many-django-objects\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">ListView</span></code>: 使用多个 Django 对象<a class=\"heading-anchor\" href=\"#listview-working-with-many-django-objects\"><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/models/querysets/#django.db.models.query.QuerySet\" title=\"django.db.models.query.QuerySet\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code></a> ，然后我们需要使用那个对象列表来使用合适的模板制作 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> 。</p>\n<p>为了获取对象，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> ，它提供 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.paginate_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.paginate_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">paginate_queryset()</span></code></a> 。不像 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> ，这里不需要 URL 的某些部分来找出要使用的查询集，因此只使用在视图类上的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.queryset\" title=\"django.views.generic.list.MultipleObjectMixin.queryset\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">queryset</span></code></a> 或  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.model\" title=\"django.views.generic.list.MultipleObjectMixin.model\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">model</span></code></a> 属性即可。覆盖 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset\" title=\"django.views.generic.list.MultipleObjectMixin.get_queryset\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code></a> 的常见原因是动态改变对象，比如根据当前对象在将来排除帖子。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> 也会覆盖 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data\" title=\"django.views.generic.base.ContextMixin.get_context_data\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code></a> 来包含适合分页的上下文变量（如果关闭分页则提供虚假分页）。它依赖 <code class=\"docutils literal notranslate\"><span class=\"pre\">object_list</span></code> 作为关键字参数来传入，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 排列它。</p>\n<p>要创建 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/template-response/#django.template.response.TemplateResponse\" title=\"django.template.response.TemplateResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponse</span></code></a> ，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 然后使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectTemplateResponseMixin</span></code></a> ；与上面的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> 一样，它覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_template_names()</span></code> 来提供一系列选择，最常用的是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app_label&gt;/&lt;model_name&gt;_list.html</span></code> ，<code class=\"docutils literal notranslate\"><span class=\"pre\">_list</span></code> 部分再次从 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix\" title=\"django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name_suffix</span></code></a> 属性中获取。（基于日期的通用视图使用诸如  <code class=\"docutils literal notranslate\"><span class=\"pre\">_archive</span></code> 、<code class=\"docutils literal notranslate\"><span class=\"pre\">_archive_year</span></code> 等的后缀来为各种专门的基于类的列表视图使用不同模板。）</p>\n</section>\n</section>\n<section id=\"using-django-s-class-based-view-mixins\">\n<h2>使用 Django 的基于类的视图 mixins<a class=\"heading-anchor\" href=\"#using-django-s-class-based-view-mixins\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>现在我们已经知道 Django 的基于类的通用视图如何使用提供的mixins ，让我们看看结合它们的其他方式。当然，我们仍然准备将它们和内置的基于类的视图或其他基于类的通用视图结合在一起，但是你可以解决的一系列罕见问题，而不是使用 Django 提供的开箱即用的方法。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>不是所有的mixins能被一起使用，并且不是所有的基于类的通用视图能和所有其他mixins一起使用。这里我们介绍一些有用的例子；如果你想集合其他功能，那么你将必须考虑你正在使用的不同类之间的重叠的属性和方法之间的交互，还有方法解析顺序如何影响这些方法的版本将以何种顺序调用。</p>\n<p>Django 的有关  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/\"><span class=\"doc\">class-based views</span></a> and <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins/\"><span class=\"doc\">class-based view mixins</span></a>  的参考文档将帮助你理解哪一些属性和方法可能导致不同类和mixins之间的冲突。</p>\n<p>如果有疑问，通常最好是回退并最好在 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#View\" title=\"View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> 上工作，或许使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> 。尽管你有可能最后写了很多代码，但它会被其他后来者理解，而且你节省了很多精力在沟通上面。（当然，你可以随时了解使用 Django 实现的基于类的通用视图，来获取如何解决问题的灵感。）</p>\n</aside>\n<section id=\"using-singleobjectmixin-with-view\">\n<h3>视图和 <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> 一起使用<a class=\"heading-anchor\" href=\"#using-singleobjectmixin-with-view\"><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\">POST</span></code> 的基于类的视图，我们将子类化 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/base/#django.views.generic.base.View\" title=\"django.views.generic.base.View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a>  并且在子类中编写一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 方法。你希望我们的处理工作在一个来自 URL 标识的特定的对象，我们将需要 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 提供的功能。</p>\n<p>我们将使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> 模型来演示。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">views.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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 code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span><span class=\"p\">,</span> <span class=\"n\">HttpResponseRedirect</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">View</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">RecordInterest</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">View</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;Records the current user&#39;s interest in an author.&quot;&quot;&quot;</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</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\">HttpResponseForbidden</span><span class=\"p\">()</span>\n\n        <span class=\"c1\"># Look up the author we&#39;re interested in.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"c1\"># Actually record interest somehow here!</span>\n\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponseRedirect</span><span class=\"p\">(</span><span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;author-detail&#39;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">}))</span>\n</code></pre></figure>\n<p>在实践中，你可能想用键值存储记录爱好，而不是关系数据库，因为我们保留了这一点。唯一需要注意的是使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 时，我们希望查找感兴趣的作者的地方，它需要调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.get_object()</span></code> 。其他则由 mixin 负责。</p>\n<p>我们完全可以简单的将它连接在 URLs 中：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">urls.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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 code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">path</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">RecordInterest</span>\n\n<span class=\"n\">urlpatterns</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\">#...</span>\n    <span class=\"n\">path</span><span class=\"p\">(</span><span class=\"s1\">&#39;author/&lt;int:pk&gt;/interest/&#39;</span><span class=\"p\">,</span> <span class=\"n\">RecordInterest</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">(),</span> <span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s1\">&#39;author-interest&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>注意 <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> 命名的组，<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a> 用它来检查 <code class=\"docutils literal notranslate\"><span class=\"pre\">Author</span></code> 实例。你也可以使用 slug，或者 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 的任何其他功能。</p>\n</section>\n<section id=\"using-singleobjectmixin-with-listview\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">ListView</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> 一起使用<a class=\"heading-anchor\" href=\"#using-singleobjectmixin-with-listview\"><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/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 提供内置的分页，但你可能想对所有被链接到其他对象的对象列表进行分页。在这个例子里，你可以想对特定出版者的所有书籍进行分页。</p>\n<p>一个办法是将 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a>  结合 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 使用，因此书籍分页列表的查询集挂上找到的出版者（作为单个对象）。为了实现它，我们需要两个不同的查询集：</p>\n<dl class=\"simple\">\n<dt><a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 使用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Book</span></code> 查询集</dt><dd><p>因为我们已经访问了 我们想要书籍列表的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> ，我们只需覆盖 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> 并使用反向外键管理（<a class=\"reference internal\" href=\"/zh-hans/3.0/topics/db/queries/#backwards-related-objects\"><span class=\"std std-ref\">reverse foreign key manager</span></a>）。</p>\n</dd>\n<dt>在 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object\" title=\"django.views.generic.detail.SingleObjectMixin.get_object\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_object()</span></code></a> 里使用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> 查询集</dt><dd><p>我们将依赖 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</span></code> 的默认实现来获取正确的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> 对象。我们需要显式地传递 <code class=\"docutils literal notranslate\"><span class=\"pre\">queryset</span></code> 参数，因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</span></code> 的默认实现会调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> ，我们已经覆盖了它并返回了 <code class=\"docutils literal notranslate\"><span class=\"pre\">Book</span></code> 对象而不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> 对象。</p>\n</dd>\n</dl>\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\">get_context_data()</span></code>。由于 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 和  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 会将上下文数据放在 <code class=\"docutils literal notranslate\"><span class=\"pre\">context_object_name</span></code> 的值下（如果它已设置），我们要确保 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> 在上下文数据中。<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 将为我们添加合适的 <code class=\"docutils literal notranslate\"><span class=\"pre\">page_obj</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">paginator</span></code> （如果我们记得调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code> 的话）。</p>\n</aside>\n<p>现在我们编写一个新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">PublisherDetail</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.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ListView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Publisher</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PublisherDetail</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">ListView</span><span class=\"p\">):</span>\n    <span class=\"n\">paginate_by</span> <span class=\"o\">=</span> <span class=\"mi\">2</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;books/publisher_detail.html&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">(</span><span class=\"n\">queryset</span><span class=\"o\">=</span><span class=\"n\">Publisher</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">())</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_context_data</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;publisher&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_queryset</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\">object</span><span class=\"o\">.</span><span class=\"n\">book_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>注意看我们如何在 <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> 中设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.object</span></code> ，这样我们以后可以在 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> 和  <code class=\"docutils literal notranslate\"><span class=\"pre\">get_queryset()</span></code> 中再次使用它。如果你没有设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ，模板将默认为 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 选项，在这个例子里是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;books/book_list.html&quot;</span></code> ，因为它是书籍列表；<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#ListView\" title=\"ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 对 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 一无所知，因此这个视图和 <code class=\"docutils literal notranslate\"><span class=\"pre\">Publisher</span></code> 没有任何关系。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">paginate_by</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    <span class=\"p\">&lt;</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>Publisher <span class=\"cp\">{{</span> <span class=\"nv\">publisher.name</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">h2</span><span class=\"p\">&gt;</span>\n\n    <span class=\"p\">&lt;</span><span class=\"nt\">ol</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">book</span> <span class=\"k\">in</span> <span class=\"nv\">page_obj</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">book.title</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">li</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">ol</span><span class=\"p\">&gt;</span>\n\n    <span class=\"p\">&lt;</span><span class=\"nt\">div</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;pagination&quot;</span><span class=\"p\">&gt;</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">span</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;step-links&quot;</span><span class=\"p\">&gt;</span>\n            <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">page_obj.has_previous</span> <span class=\"cp\">%}</span>\n                <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;?page=</span><span class=\"cp\">{{</span> <span class=\"nv\">page_obj.previous_page_number</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>previous<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</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\">span</span> <span class=\"na\">class</span><span class=\"o\">=</span><span class=\"s\">&quot;current&quot;</span><span class=\"p\">&gt;</span>\n                Page <span class=\"cp\">{{</span> <span class=\"nv\">page_obj.number</span> <span class=\"cp\">}}</span> of <span class=\"cp\">{{</span> <span class=\"nv\">paginator.num_pages</span> <span class=\"cp\">}}</span>.\n            <span class=\"p\">&lt;/</span><span class=\"nt\">span</span><span class=\"p\">&gt;</span>\n\n            <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">page_obj.has_next</span> <span class=\"cp\">%}</span>\n                <span class=\"p\">&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;?page=</span><span class=\"cp\">{{</span> <span class=\"nv\">page_obj.next_page_number</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>next<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;</span>\n            <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;/</span><span class=\"nt\">span</span><span class=\"p\">&gt;</span>\n    <span class=\"p\">&lt;/</span><span class=\"nt\">div</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"avoid-anything-more-complex\">\n<h2>避免过度复杂的事情<a class=\"heading-anchor\" href=\"#avoid-anything-more-complex\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>当你使用它们的功能时，通常你可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a> 和  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 。如上所示，你甚至可以将 <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView\" title=\"django.views.generic.list.ListView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ListView</span></code></a> 结合起来。然而当你试着这么做时，事情将变得复杂，一个好的经验法则是：</p>\n<aside class=\"admonition admonition-hint\">\n<p class=\"admonition-title\">Hint</p>\n<p>你的每个视图应该只使用 mixins 或者来自一个通用基于类的视图的组里视图：<span class=\"xref std std-doc\">detail, list1</span>, <span class=\"xref std std-doc\">editing2</span> 和日期。举例它将 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> (在视图里内建) 和  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin\" title=\"django.views.generic.list.MultipleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code></a> (通用列表) 结合起来，但你可能会在 <code class=\"docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code> (通用详情) 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">MultipleObjectMixin</span></code> 结合时遇到问题。</p>\n</aside>\n<p>为了给你展示当变得复杂时发生了什么，我们显示了一个例子，当这里有一个更简单的解决方案时，我们牺牲了可读写和可维护性。首先，让我们试着结合 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 和  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> ，这样当我们使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 显示对象时，可以  <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> 一个 <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> 到同样的 URL 里。</p>\n<section id=\"using-formmixin-with-detailview\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">DetailView</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code> 一起使用<a class=\"heading-anchor\" href=\"#using-formmixin-with-detailview\"><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/class-based-views/flattened-index/#View\" title=\"View\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">View</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> 的例子。我们已经记录了用户对特定作者的喜好；现在我们需要留言说为什么我们喜欢他们。再次说明，我们假设不在关系数据里保存它，而存储在更难理解的东西里，我们现在先不考虑细节。</p>\n<p>在这点上，很自然的找到一个 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> 来封装从浏览器传递到 Django 的信息。也可以说我们在 REST 上投入了很多精力，我们想使用相同的 URL 来显示作者，以便从用户那里捕获信息。让我们重写 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetailView</span></code> 来实现吧。</p>\n<p>我们将保持 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 来处理 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</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> ，但这样我们就可以在模板里渲染它。我们也想从 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> 中引入表单处理并编写一些代码，这样在 <code class=\"docutils literal notranslate\"><span class=\"pre\">POST</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/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> 并亲自实现了 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> ，而不是试着把 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> （也提供合适的 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code>）混着用，因为这两个视图实现了 <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> ，这样会让事情变得更复杂。</p>\n</aside>\n<p>新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetail</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=\"c1\"># CAUTION: you almost certainly do not want to do this.</span>\n<span class=\"c1\"># It is provided as part of a discussion of problems you can</span>\n<span class=\"c1\"># run into when combining different generic class-based view</span>\n<span class=\"c1\"># functionality that is not designed to be used together.</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">forms</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DetailView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.edit</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">FormMixin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterestForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">Form</span><span class=\"p\">):</span>\n    <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">()</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorDetail</span><span class=\"p\">(</span><span class=\"n\">FormMixin</span><span class=\"p\">,</span> <span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n    <span class=\"n\">form_class</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_success_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;author-detail&#39;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">})</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</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\">HttpResponseForbidden</span><span class=\"p\">()</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"n\">form</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_form</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=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">form_valid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">form_invalid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">form_valid</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">form</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Here, we would record the user&#39;s interest using the message</span>\n        <span class=\"c1\"># passed in form.cleaned_data[&#39;message&#39;]</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">form_valid</span><span class=\"p\">(</span><span class=\"n\">form</span><span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_success_url()``提供了重定向的去处，它在</span> <span class=\"pre\">``form_valid()</span></code> 的默认实现中使用。如前所述，我们需要提供自己的 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 。</p>\n</section>\n<section id=\"a-better-solution\">\n<h3>更好的解决方案<a class=\"heading-anchor\" href=\"#a-better-solution\"><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/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin\" title=\"django.views.generic.edit.FormMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormMixin</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 之间细微的联系已经在测试我们管理事务的能力了。你不太可能想写这样的类。</p>\n<p>在这个例子里，你可以编写 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 让 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</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>\n<p>或者，使用单独的视图来处理表单仍然比上述方法工作量小，它可以使用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView\" title=\"django.views.generic.edit.FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> ，而不必担心任何问题。</p>\n</section>\n<section id=\"an-alternative-better-solution\">\n<h3>另一种更好的解决方案<a class=\"heading-anchor\" href=\"#an-alternative-better-solution\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>我们在这里尝试使用来自相同 URL 的两种不同的基于类的视图。我们为什么要这样做？<code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 请求应该获取 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#DetailView\" title=\"DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</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> 添加到上下文数据中），<code class=\"docutils literal notranslate\"><span class=\"pre\">POST</span></code> 请求应该获取 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a> 。让我们首先设置这些视图吧。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDisplay</span></code> 视图几乎与 <a class=\"reference internal\" href=\"/zh-hans/3.0/topics/class-based-views/generic-display/#generic-views-extra-work\"><span class=\"std std-ref\">当我们第一次介绍AuthorDetail时</span></a> 相同。我们必须编写自己的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data()</span></code> 来使 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterestForm</span></code> 可用于模板。为清楚所见，我们将跳过重写 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_object()</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</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">forms</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">DetailView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Author</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterestForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">Form</span><span class=\"p\">):</span>\n    <span class=\"n\">message</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">()</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorDisplay</span><span class=\"p\">(</span><span class=\"n\">DetailView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_context_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">context</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">get_context_data</span><span class=\"p\">(</span><span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n        <span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s1\">&#39;form&#39;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n</code></pre></div>\n<p>然后 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterest</span></code> 是一个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#FormView\" title=\"FormView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FormView</span></code></a>，但我们必须带入到 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin\" title=\"django.views.generic.detail.SingleObjectMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectMixin</span></code></a> ，这样我们才可以找到我们正在谈论的作者，并且我们必须记住要设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> 来确保表单错误与 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 上使用的 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDisplay</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.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponseForbidden</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.urls</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">reverse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">FormView</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectMixin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorInterest</span><span class=\"p\">(</span><span class=\"n\">SingleObjectMixin</span><span class=\"p\">,</span> <span class=\"n\">FormView</span><span class=\"p\">):</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;books/author_detail.html&#39;</span>\n    <span class=\"n\">form_class</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterestForm</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Author</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</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\">HttpResponseForbidden</span><span class=\"p\">()</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_object</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_success_url</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">reverse</span><span class=\"p\">(</span><span class=\"s1\">&#39;author-detail&#39;</span><span class=\"p\">,</span> <span class=\"n\">kwargs</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;pk&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">object</span><span class=\"o\">.</span><span class=\"n\">pk</span><span class=\"p\">})</span>\n</code></pre></div>\n<p>最后我们将它们一起放在新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorDetail</span></code> 视图中。我们已经知道在一个基于类的视图上调用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">as_view()</span></code></a> 方法带给我们像基于函数的视图一样的东西，所以我们可以在两个子视图直接进行选择。</p>\n<p>你当然可以像在 URLconf 中一样将关键字参数传递到  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/base/#django.views.generic.base.View.as_view\" title=\"django.views.generic.base.View.as_view\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">as_view()</span></code></a> ，比如你想 <code class=\"docutils literal notranslate\"><span class=\"pre\">AuthorInterest</span></code> 行为显示到其他 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.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">View</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AuthorDetail</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\">get</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">view</span> <span class=\"o\">=</span> <span class=\"n\">AuthorDisplay</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n        <span class=\"n\">view</span> <span class=\"o\">=</span> <span class=\"n\">AuthorInterest</span><span class=\"o\">.</span><span class=\"n\">as_view</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"o\">*</span><span class=\"n\">args</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这个方式也可以被任何其他通用基于类的视图或你自己实现的直接继承自:class:View 或 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/flattened-index/#TemplateView\" title=\"TemplateView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code></a> 使用，因为它使不同视图尽可能分离。</p>\n</section>\n</section>\n<section id=\"more-than-just-html\">\n<span id=\"jsonresponsemixin-example\"></span><h2>不仅仅是HTML<a class=\"heading-anchor\" href=\"#more-than-just-html\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>基于类的视图的优势是你可以多次执行相同操作。假设你正在编写API，那么每个视图应该返回 JSON，而不是渲染HTML。</p>\n<p>我们可以创建一个 mixin 类来在所有视图里使用，它用来进行一次转换JSON。</p>\n<p>比如，一个 JSON mixin 可以是这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">JsonResponse</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONResponseMixin</span><span class=\"p\">:</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    A mixin that can be used to render a JSON response.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_json_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Returns a JSON response, transforming &#39;context&#39; to make the payload.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">return</span> <span class=\"n\">JsonResponse</span><span class=\"p\">(</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_data</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">),</span>\n            <span class=\"o\">**</span><span class=\"n\">response_kwargs</span>\n        <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_data</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Returns an object that will be serialized as JSON by json.dumps().</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"c1\"># Note: This is *EXTREMELY* naive; in reality, you&#39;ll need</span>\n        <span class=\"c1\"># to do much more complex handling to ensure that arbitrary</span>\n        <span class=\"c1\"># objects -- such as Django model instances or querysets</span>\n        <span class=\"c1\"># -- can be serialized as JSON.</span>\n        <span class=\"k\">return</span> <span class=\"n\">context</span>\n</code></pre></div>\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/serialization/\"><span class=\"doc\">Serializing Django objects</span></a> 文档来获取更多有关如何正确转换 Django 模型和查询集为 JSON。</p>\n</aside>\n<p>mixin 提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_json_response()</span></code> 方法，其签名与 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code></a> 相同。为了使用它，我们需要把它混在 <code class=\"docutils literal notranslate\"><span class=\"pre\">TemplateView</span></code> 里，并且重写 <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_response()</span></code> 来调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">render_to_json_response()</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.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TemplateView</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONView</span><span class=\"p\">(</span><span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">TemplateView</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>同样，我们将 mixin 和其中一个通用视图一起使用。我们可以把 <code class=\"docutils literal notranslate\"><span class=\"pre\">JSONResponseMixin</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.views.generic.detail.BaseDetailView</span></code> 混合起来创建我们自己的 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 版本 （<a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</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.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseDetailView</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">JSONDetailView</span><span class=\"p\">(</span><span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">BaseDetailView</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">response_kwargs</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>然后这个视图和其他 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 使用相同方式部署，除了响应的格式外其他都相同。</p>\n<p>如果你想更激进一些，你甚至可以混合一个 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView\" title=\"django.views.generic.detail.DetailView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DetailView</span></code></a> 子类，它可以根据 HTTP 请求的一些特性（比如一个查询参数或HTTP请求头），同时返回 HTML 和 JSON。只需混合 <code class=\"docutils literal notranslate\"><span class=\"pre\">JSONResponseMixin</span></code> 和 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin\" title=\"django.views.generic.detail.SingleObjectTemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SingleObjectTemplateResponseMixin</span></code></a> ，并重写  <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response\" title=\"django.views.generic.base.TemplateResponseMixin.render_to_response\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">render_to_response()</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.views.generic.detail</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SingleObjectTemplateResponseMixin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">HybridDetailView</span><span class=\"p\">(</span><span class=\"n\">JSONResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">SingleObjectTemplateResponseMixin</span><span class=\"p\">,</span> <span class=\"n\">BaseDetailView</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">render_to_response</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">context</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Look for a &#39;format=json&#39; GET argument</span>\n        <span class=\"k\">if</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">request</span><span class=\"o\">.</span><span class=\"n\">GET</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">&#39;format&#39;</span><span class=\"p\">)</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;json&#39;</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">render_to_json_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">render_to_response</span><span class=\"p\">(</span><span class=\"n\">context</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>由于 Python 解决方法重载的方式，对 <code class=\"docutils literal notranslate\"><span class=\"pre\">super().render_to_response(context)</span></code> 的调用最终会调用 <a class=\"reference internal\" href=\"/zh-hans/3.0/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin\" title=\"django.views.generic.base.TemplateResponseMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TemplateResponseMixin</span></code></a> 的 的:meth:~django.views.generic.base.TemplateResponseMixin.render_to_response() 实现。</p>\n</section>","rootId":"using-mixins-with-class-based-views","toc":[{"title":"上下文和模板响应","anchor":"context-and-template-responses","children":[]},{"title":"构造 Django 基于类的通用视图","anchor":"building-up-django-s-generic-class-based-views","children":[{"title":"DetailView ：使用单个 Django 对象","anchor":"detailview-working-with-a-single-django-object","children":[]},{"title":"ListView: 使用多个 Django 对象","anchor":"listview-working-with-many-django-objects","children":[]}]},{"title":"使用 Django 的基于类的视图 mixins","anchor":"using-django-s-class-based-view-mixins","children":[{"title":"视图和 SingleObjectMixin 一起使用","anchor":"using-singleobjectmixin-with-view","children":[]},{"title":"ListView 和 SingleObjectMixin 一起使用","anchor":"using-singleobjectmixin-with-listview","children":[]}]},{"title":"避免过度复杂的事情","anchor":"avoid-anything-more-complex","children":[{"title":"DetailView 和 FormMixin 一起使用","anchor":"using-formmixin-with-detailview","children":[]},{"title":"更好的解决方案","anchor":"a-better-solution","children":[]},{"title":"另一种更好的解决方案","anchor":"an-alternative-better-solution","children":[]}]},{"title":"不仅仅是HTML","anchor":"more-than-just-html","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/3.0/topics/"},{"docname":"topics/class-based-views/index","title":"基于类的视图","url":"/zh-hans/3.0/topics/class-based-views/"}],"prev":{"docname":"topics/class-based-views/generic-editing","title":"使用基于类的视图处理表单","url":"/zh-hans/3.0/topics/class-based-views/generic-editing/"},"next":{"docname":"topics/migrations","title":"迁移","url":"/zh-hans/3.0/topics/migrations/"},"formats":{"html":"/zh-hans/3.0/topics/class-based-views/mixins/","markdown":"/zh-hans/3.0/topics/class-based-views/mixins.md","json":"/zh-hans/3.0/topics/class-based-views/mixins.json"},"source":"https://github.com/django/django/blob/stable/3.0.x/docs/topics/class-based-views/mixins.txt","official":"https://docs.djangoproject.com/zh-hans/3.0/topics/class-based-views/mixins/","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"]}