基于类的视图 — Django 文档

来自菜鸟教程
Django/docs/3.2.x/topics/class-based-views/index
跳转至:导航、​搜索

基于类的视图

视图是可调用的,它接受请求并返回响应。 这不仅仅是一个函数,Django 提供了一些可用作视图的类的示例。 这些允许您通过利用继承和混合来构建视图并重用代码。 还有一些我们稍后会介绍的任务的通用视图,但您可能希望设计适合您用例的自己的可重用视图结构。 有关完整的详细信息,请参阅 基于类的视图参考文档

基本示例

Django 提供了适用于各种应用程序的基本视图类。 所有视图都继承自 View 类,该类处理将视图链接到 URL、HTTP 方法调度和其他常见功能。 RedirectView 提供了 HTTP 重定向,而 TemplateView 扩展了基类使其也呈现模板。


在您的 URLconf 中的用法

使用通用视图最直接的方法是直接在 URLconf 中创建它们。 如果您只更改基于类的视图上的几个属性,您可以将它们传递给 as_view() 方法调用本身:

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path('about/', TemplateView.as_view(template_name="about.html")),
]

传递给 as_view() 的任何参数都将覆盖在类上设置的属性。 在本例中,我们在 TemplateView 上设置了 template_name。 类似的覆盖模式可用于 RedirectView 上的 url 属性。


子类化通用视图

使用通用视图的第二种更强大的方法是从现有视图继承并覆盖子类中的属性(例如 template_name)或方法(例如 get_context_data)以提供新值或方法。 例如,考虑一个仅显示一个模板 about.html 的视图。 Django 有一个通用视图来执行此操作 - TemplateView - 因此我们可以将其子类化,并覆盖模板名称:

# some_app/views.py
from django.views.generic import TemplateView

class AboutView(TemplateView):
    template_name = "about.html"

然后我们需要将这个新视图添加到我们的 URLconf 中。 TemplateView 是一个类,而不是一个函数,所以我们将 URL 指向 as_view() 类方法,它为基于类的视图提供了一个类似函数的入口:

# urls.py
from django.urls import path
from some_app.views import AboutView

urlpatterns = [
    path('about/', AboutView.as_view()),
]

有关如何使用内置通用视图的更多信息,请参阅关于 基于类的通用视图 的下一个主题。

支持其他 HTTP 方法

假设有人想使用视图作为 API 通过 HTTP 访问我们的图书库。 API 客户端会不时连接并下载自上次访问以来已出版书籍的书籍数据。 但是,如果此后没有新书出现,那么从数据库中获取书籍、呈现完整响应并将其发送到客户端将浪费 CPU 时间和带宽。 最好在最新一本书出版时询问 API。

我们将 URL 映射到 URLconf 中的图书列表视图:

from django.urls import path
from books.views import BookListView

urlpatterns = [
    path('books/', BookListView.as_view()),
]

和观点:

from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
    model = Book

    def head(self, *args, **kwargs):
        last_book = self.get_queryset().latest('publication_date')
        response = HttpResponse(
            # RFC 1123 date format.
            headers={'Last-Modified': last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')},
        )
        return response

如果视图是从 GET 请求访问的,则响应中会返回一个对象列表(使用 book_list.html 模板)。 但是,如果客户端发出 HEAD 请求,则响应的正文为空,并且 Last-Modified 标头指示最近一本书的出版时间。 基于此信息,客户端可能会或可能不会下载完整的对象列表。