Представления на основе классов

Представление - это вызываемый объект, который принимает запрос и возвращает ответ. Это может быть не просто функция, и Django предоставляет пример некоторых классов, которые могут быть использованы в качестве представлений. Они позволяют структурировать ваши представления и повторно использовать код, используя наследование и миксины. Есть также несколько общих представлений для задач, к которым мы вернемся позже, но вы, возможно, захотите разработать свою собственную структуру многократно используемых представлений, которая подходит для вашего случая использования. Для получения подробной информации смотрите class-based views reference documentation.

Основные примеры

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(), будут переопределять атрибуты, установленные на классе. В этом примере мы установили template_name на TemplateView. Аналогичная схема переопределения может быть использована для атрибута url на RedirectView.

Подклассификация общих представлений

Второй, более мощный способ использования общих представлений - наследование от существующего представления и переопределение атрибутов (таких как 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

Предположим, кто-то хочет получить доступ к нашей библиотеке книг по HTTP, используя представления в качестве API. Клиент API будет подключаться время от времени и загружать данные о книгах, опубликованных с момента последнего посещения. Но если с тех пор не появилось новых книг, то это пустая трата процессорного времени и пропускной способности, чтобы получить книги из базы данных, выдать полный ответ и отправить его клиенту. Возможно, будет предпочтительнее спросить 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 указывает, когда была опубликована последняя книга. Основываясь на этой информации, клиент может загрузить или не загрузить полный список объектов.

Асинхронные представления на основе классов

Помимо уже показанных синхронных (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. Исключение ImproperlyConfigured будет поднято в as_view(), если объявления def и async def будут смешаны.

Django автоматически определяет асинхронные представления и запускает их в асинхронном контексте. Подробнее об асинхронной поддержке Django и о том, как лучше использовать асинхронные представления, вы можете прочитать в Поддержка асинхронного режима.

Вернуться на верх