基于类的视图¶
视图是可调用的,能接受用户的请求并返回响应。视图远不只是个函数,Django提供了一些可用作视图的类的示例,允许你通过继承和复用构建自己的视图并且复用这些代码。虽然接下来还会介绍一些用于任务的通用视图,但你可能想自己设计可复用的视图结构,以便针对某些特殊场景。详情请见 class-based views reference documentation</ref/class-based-views/index> 。
基础示例¶
Django 提供了适用于很多应用的基本视图类。所有视图继承自 View 类,它处理视图链接到 URLs,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()),
]
有关如何使用内建通用视图的更多信息,请查阅在 generic class-based views 的下一个主题。
支持其他 HTTP 方法¶
如果某人想将视图作为 API 来访问图书馆。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
If the view is accessed from a GET request, an object list is returned in
the response (using the book_list.html template). But if the client issues
a HEAD request, the response has an empty body and the Last-Modified
header indicates when the most recent book was published. Based on this
information, the client may or may not download the full object list.
异步类视图¶
除了已经展示的同步(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 def。如果混合使用了 def 和 async def 声明,将会在 as_view() 中引发 ImproperlyConfigured 异常。
Django 会自动检测异步视图并在异步上下文中运行它们。您可以在 异步支持 中详细了解 Django 的异步支持以及如何最佳使用异步视图。