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