# Django 2.2.9.dev20191202104323 文档

# 基于类的视图

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

- 基于类的视图
- 内置的基于类的通用视图
- 使用基于类的视图处理表单
- 与基于类的视图一起使用 mixins

## 基础示例

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
            response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
            return response

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