基于类的视图

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

基本示例

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 最近发布的书籍是什么时候可能更好。

我们在 URLconf 中将 URL 映射到书籍列表视图

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 标头指示最近发布的书籍是什么时候。根据此信息,客户端可能会或可能不会下载完整对象列表。

异步基于类的视图

除了已经显示的同步(def)方法处理程序外,View 子类可以定义异步(async def)方法处理程序,以使用await 利用异步代码

import asyncio
from django.http import HttpResponse
from django.views import View


class AsyncView(View):
    async def get(self, request, *args, **kwargs):
        # Perform io-blocking view logic using await, sleep for example.
        await asyncio.sleep(1)
        return HttpResponse("Hello async world!")

在单个视图类中,所有用户定义的方法处理程序必须全部是同步的,使用def,或者全部是异步的,使用async defImproperlyConfigured 异常将在as_view() 中引发,如果混合使用了defasync def 声明。

Django 将自动检测异步视图并在异步上下文中运行它们。您可以在异步支持 中阅读有关 Django 的异步支持以及如何最好地使用异步视图的更多信息。

返回顶部