{"title":"基于类的视图","version":"6.1","locale":"zh-hans","docname":"topics/class-based-views/index","url":"/zh-hans/6.1/topics/class-based-views/","canonical":"https://djangodocs.dev/zh-hans/6.1/topics/class-based-views/","summary":"视图是可调用的，能接受用户的请求并返回响应。视图远不只是个函数，Django提供了一些可用作视图的类的示例，允许你通过继承和复用构建自己的视图并且复用这些代码。虽然接下来还会介绍一些用于任务的通用视图，但你可能想自己设计可复用的视图结构，以便针对某些特殊场景。详情请见 class-based views reference…","html":"<h1>基于类的视图<a class=\"heading-anchor\" href=\"#class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>视图是可调用的，能接受用户的请求并返回响应。视图远不只是个函数，Django提供了一些可用作视图的类的示例，允许你通过继承和复用构建自己的视图并且复用这些代码。虽然接下来还会介绍一些用于任务的通用视图，但你可能想自己设计可复用的视图结构，以便针对某些特殊场景。详情请见 class-based views reference documentation&lt;/ref/class-based-views/index&gt; 。</p>\n<div class=\"toctree-wrapper compound\">\n<ul>\n<li class=\"toctree-l1\"><a class=\"reference internal\" href=\"/zh-hans/6.1/topics/class-based-views/intro/\">基于类的视图</a></li>\n<li class=\"toctree-l1\"><a class=\"reference internal\" href=\"/zh-hans/6.1/topics/class-based-views/generic-display/\">内置的基于类的通用视图</a></li>\n<li class=\"toctree-l1\"><a class=\"reference internal\" href=\"/zh-hans/6.1/topics/class-based-views/generic-editing/\">使用基于类的视图处理表单</a></li>\n<li class=\"toctree-l1\"><a class=\"reference internal\" href=\"/zh-hans/6.1/topics/class-based-views/mixins/\">在基于类的视图中使用混入</a></li>\n</ul>\n</div>\n<section id=\"basic-examples\">\n<h2>基础示例<a class=\"heading-anchor\" href=\"#basic-examples\"><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/6.1/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> 类，它处理视图链接到 URLs，HTTP 方法调度和其他简单功能。<a class=\"reference internal\" href=\"/zh-hans/6.1/ref/class-based-views/base/#django.views.generic.base.RedirectView\" title=\"django.views.generic.base.RedirectView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RedirectView</span></code></a> 用于 HTTP 重定向，<a class=\"reference internal\" href=\"/zh-hans/6.1/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> 扩展基类来使它能渲染模板。</p>\n</section>\n<section id=\"usage-in-your-urlconf\">\n<h2>在 URLconf 中的用法<a class=\"heading-anchor\" href=\"#usage-in-your-urlconf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>使用通用视图最直接的方式是在 URLconf 中直接创建它们。如果你只在基于类的视图上改变一些属性，那么你可以把它们传递到 <a class=\"reference internal\" href=\"/zh-hans/6.1/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<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.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\">django.views.generic</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TemplateView</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=\"s2\">&quot;about/&quot;</span><span class=\"p\">,</span> <span class=\"n\">TemplateView</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=\"s2\">&quot;about.html&quot;</span><span class=\"p\">)),</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>任何传递到 <a class=\"reference internal\" href=\"/zh-hans/6.1/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\">TemplateView</span></code> 上设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> 。一个相似的覆盖模式可用于 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/class-based-views/base/#django.views.generic.base.RedirectView\" title=\"django.views.generic.base.RedirectView\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RedirectView</span></code></a> 上的 <code class=\"docutils literal notranslate\"><span class=\"pre\">url</span></code> 属性。</p>\n</section>\n<section id=\"subclassing-generic-views\">\n<h2>子类化通用视图<a class=\"heading-anchor\" href=\"#subclassing-generic-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>第二，使用通用视图更有力的方式是继承已存在的视图并覆盖子类里的属性（比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">template_name</span></code> ）或方法（比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_context_data</span></code> ）来提供新的值或方法。例如，考虑只显示一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">about.html</span></code> 模板的视图。Django 的 <a class=\"reference internal\" href=\"/zh-hans/6.1/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> 可以完成这个工作，因此我们可以将其子类化并重写模板名称：</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\"># some_app/views.py</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\">TemplateView</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AboutView</span><span class=\"p\">(</span><span class=\"n\">TemplateView</span><span class=\"p\">):</span>\n    <span class=\"n\">template_name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;about.html&quot;</span>\n</code></pre></div>\n<p>最后我们需要在 URLconf 中添加这个新视图。<a class=\"reference internal\" href=\"/zh-hans/6.1/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> 只是一个类，而不是一个函数，因此我们将 URL 指向 <a class=\"reference internal\" href=\"/zh-hans/6.1/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<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\"># urls.py</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\">path</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">some_app.views</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AboutView</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=\"s2\">&quot;about/&quot;</span><span class=\"p\">,</span> <span class=\"n\">AboutView</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>有关如何使用内建通用视图的更多信息，请查阅在 <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/class-based-views/generic-display/\"><span class=\"doc\">generic class-based views</span></a> 的下一个主题。</p>\n<section id=\"supporting-other-http-methods\">\n<span id=\"id1\"></span><h3>支持其他 HTTP 方法<a class=\"heading-anchor\" href=\"#supporting-other-http-methods\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果某人想将视图作为 API 来访问图书馆。API 客户端会时不时地连接并下载上次访问过后出版的书籍数据。但如果没有新的书籍出现，那么从数据库中获取书籍，渲染一个完整响应并发送它到客户端的话，这将浪费CPU时间和带宽。当出版最新的书时，它访问 API 最好。</p>\n<p>我们需要在 URLconf 中映射 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.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\">BookListView</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=\"s2\">&quot;books/&quot;</span><span class=\"p\">,</span> <span class=\"n\">BookListView</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>还有视图：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.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\">books.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Book</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">BookListView</span><span class=\"p\">(</span><span class=\"n\">ListView</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Book</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">head</span><span class=\"p\">(</span><span class=\"bp\">self</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\">last_book</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">get_queryset</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">latest</span><span class=\"p\">(</span><span class=\"s2\">&quot;publication_date&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span>\n            <span class=\"c1\"># RFC 1123 date format.</span>\n            <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span>\n                <span class=\"s2\">&quot;Last-Modified&quot;</span><span class=\"p\">:</span> <span class=\"n\">last_book</span><span class=\"o\">.</span><span class=\"n\">publication_date</span><span class=\"o\">.</span><span class=\"n\">strftime</span><span class=\"p\">(</span>\n                    <span class=\"s2\">&quot;</span><span class=\"si\">%a</span><span class=\"s2\">, </span><span class=\"si\">%d</span><span class=\"s2\"> %b %Y %H:%M:%S GMT&quot;</span>\n                <span class=\"p\">)</span>\n            <span class=\"p\">},</span>\n        <span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">response</span>\n</code></pre></div>\n<p>If the view is accessed from a <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> request, an object list is returned in\nthe response (using the <code class=\"docutils literal notranslate\"><span class=\"pre\">book_list.html</span></code> template). But if the client issues\na <code class=\"docutils literal notranslate\"><span class=\"pre\">HEAD</span></code> request, the response has an empty body and the <code class=\"docutils literal notranslate\"><span class=\"pre\">Last-Modified</span></code>\nheader indicates when the most recent book was published. Based on this\ninformation, the client may or may not download the full object list.</p>\n</section>\n</section>\n<section id=\"asynchronous-class-based-views\">\n<span id=\"async-class-based-views\"></span><h2>异步类视图<a class=\"heading-anchor\" href=\"#asynchronous-class-based-views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>除了已经展示的同步（<code class=\"docutils literal notranslate\"><span class=\"pre\">def</span></code>）方法处理程序之外，<code class=\"docutils literal notranslate\"><span class=\"pre\">View</span></code> 子类还可以定义异步（<code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>）方法处理程序，以利用使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">await</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\">import</span><span class=\"w\"> </span><span class=\"nn\">asyncio</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\">HttpResponse</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\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AsyncView</span><span class=\"p\">(</span><span class=\"n\">View</span><span class=\"p\">):</span>\n    <span class=\"k\">async</span> <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=\"c1\"># Perform io-blocking view logic using await, sleep for example.</span>\n        <span class=\"k\">await</span> <span class=\"n\">asyncio</span><span class=\"o\">.</span><span class=\"n\">sleep</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;Hello async world!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>在单个视图类中，所有用户定义的方法处理程序必须要么是同步的，使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">def</span></code>，要么都是异步的，使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code>。如果混合使用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">def</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> 声明，将会在 <code class=\"docutils literal notranslate\"><span class=\"pre\">as_view()</span></code> 中引发 <code class=\"docutils literal notranslate\"><span class=\"pre\">ImproperlyConfigured</span></code> 异常。</p>\n<p>Django 会自动检测异步视图并在异步上下文中运行它们。您可以在 <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/async/\"><span class=\"doc\">异步支持</span></a> 中详细了解 Django 的异步支持以及如何最佳使用异步视图。</p>\n</section>","rootId":"class-based-views","toc":[{"title":"基础示例","anchor":"basic-examples","children":[]},{"title":"在 URLconf 中的用法","anchor":"usage-in-your-urlconf","children":[]},{"title":"子类化通用视图","anchor":"subclassing-generic-views","children":[{"title":"支持其他 HTTP 方法","anchor":"supporting-other-http-methods","children":[]}]},{"title":"异步类视图","anchor":"asynchronous-class-based-views","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/6.1/topics/"}],"prev":{"docname":"topics/templates","title":"模板","url":"/zh-hans/6.1/topics/templates/"},"next":{"docname":"topics/class-based-views/intro","title":"基于类的视图","url":"/zh-hans/6.1/topics/class-based-views/intro/"},"formats":{"html":"/zh-hans/6.1/topics/class-based-views/","markdown":"/zh-hans/6.1/topics/class-based-views.md","json":"/zh-hans/6.1/topics/class-based-views.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/class-based-views/index.txt","official":"https://docs.djangoproject.com/zh-hans/6.1/topics/class-based-views/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}