基于类的视图

视图是可调用的,能接受用户的请求并返回响应。视图远不只是个函数,Django提供了一些可用作视图的类的示例,允许你通过继承和复用构建自己的视图并且复用这些代码。虽然接下来还会介绍一些用于任务的通用视图,但你可能想自己设计可复用的视图结构,以便针对某些特殊场景。详情请见 class-based views reference documentation</ref/class-based-views/index> 。

基础示例

Django 提供了适用于很多应用的基本视图类。所有视图继承自 View 类,它处理视图链接到 URLs,HTTP 方法调度和其他简单功能。RedirectView 用于 HTTP 重定向,TemplateView 扩展基类来使它能渲染模板。

在 URLconf 中的用法

使用通用视图最直接的方式是在 URLconf 中直接创建它们。如果你只在基于类的视图上改变一些属性,那么你可以把它们传递到 as_view() 方法中调用:

  1. from django.urls import path
  2. from django.views.generic import TemplateView
  3. urlpatterns = [
  4. path("about/", TemplateView.as_view(template_name="about.html")),
  5. ]

任何传递到 as_view() 的参数将覆盖在类上设置的属性。在这个例子中,我们在 TemplateView 上设置 template_name 。一个相似的覆盖模式可用于 RedirectView 上的 url 属性。

子类化通用视图

第二,使用通用视图更有力的方式是继承已存在的视图并覆盖子类里的属性(比如 template_name )或方法(比如 get_context_data )来提供新的值或方法。例如,考虑只显示一个 about.html 模板的视图。Django 的 TemplateView 可以完成这个工作,因此我们可以将其子类化并重写模板名称:

  1. # some_app/views.py
  2. from django.views.generic import TemplateView
  3. class AboutView(TemplateView):
  4. template_name = "about.html"

最后我们需要在 URLconf 中添加这个新视图。TemplateView 只是一个类,而不是一个函数,因此我们将 URL 指向 as_view() ,它为基于类的视图提供一个类似函数的入口:

  1. # urls.py
  2. from django.urls import path
  3. from some_app.views import AboutView
  4. urlpatterns = [
  5. path("about/", AboutView.as_view()),
  6. ]

有关如何使用内建通用视图的更多信息,请查阅在 generic class-based views 的下一个主题。

支持其他 HTTP 方法

如果某人想将视图作为 API 来访问图书馆。API 客户端会时不时地连接并下载上次访问过后出版的书籍数据。但如果没有新的书籍出现,那么从数据库中获取书籍,渲染一个完整响应并发送它到客户端的话,这将浪费CPU时间和带宽。当出版最新的书时,它访问 API 最好。

我们需要在 URLconf 中映射 URL 到书籍列表视图:

  1. from django.urls import path
  2. from books.views import BookListView
  3. urlpatterns = [
  4. path("books/", BookListView.as_view()),
  5. ]

还有视图:

  1. from django.http import HttpResponse
  2. from django.views.generic import ListView
  3. from books.models import Book
  4. class BookListView(ListView):
  5. model = Book
  6. def head(self, *args, **kwargs):
  7. last_book = self.get_queryset().latest("publication_date")
  8. response = HttpResponse(
  9. # RFC 1123 date format.
  10. headers={
  11. "Last-Modified": last_book.publication_date.strftime(
  12. "%a, %d %b %Y %H:%M:%S GMT"
  13. )
  14. },
  15. )
  16. return response

如果从 GET 请求访问视图,将在响应(使用 book_list.html 模板)中返回一个干净的对象列表。但如果客户端发出一个 HEAD 请求,那么将响应一个空 body 和 Last-Modified 头将标识最新书籍的出版时间。基于这些信息,客户端可以选择是否下载一个完整的对象类。

异步类视图

New in Django 4.1.

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

  1. import asyncio
  2. from django.http import HttpResponse
  3. from django.views import View
  4. class AsyncView(View):
  5. async def get(self, request, *args, **kwargs):
  6. # Perform io-blocking view logic using await, sleep for example.
  7. await asyncio.sleep(1)
  8. return HttpResponse("Hello async world!")

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

Django 会自动检测异步视图并在异步上下文中运行它们。您可以在 异步支持 中详细了解 Django 的异步支持以及如何最佳使用异步视图。