Представление, в самом общем виде, - это исполняемый(callable) объект, который принимает “на вход” запрос (request), и возвращает ответ(response). В этой роли может выступать не только функция, но и классы - и Django предоставляет нам такие классы и примеры их использования. Такие классы позволяют создавать структурированные, повторно используемые представления, базируясь на возможностях наследования и, в том числе, множественного наследования, - с использованием примесей(mixins). Django включает в себя набор общих(generic) представлений, которые идеально подходят для решения ряда рутинных задач(мы рассмотрим их позже). Ну и конечно, вы можете использовать существующие классы Django для создания собственных, расширяемых и повторно используемых представлений, которые будут полностью удовлетворять вашим потребностям. За более полной информацией обратитесь к документация по классам-представлениям.
Django предлагает нам базовый набор классов представлений, который может использоваться в широком спектре приложений. Все классы-представления наследуют класс View, который обрабатывает “привязку” представления с соответствующими URL, диспетчеризацию HTTP запросов(анализ методов GET, POST и последующий вызов одноименного метода для обработки запроса) и ряд других простых действий. Класс RedirectView служит для простого HTTP перенаправления(redirect), а класс TemplateView расширяет базовый класс, предоставляя возможность обработки шаблонов.
Самый простой способ использования общих классов-представлений, - это их создание непосредственно в вашем URLconf. Если вы переопределяете всего несколько простых атрибутов класса, вы можете просто передать эти значения как аргументы метода as_view():
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^about/', TemplateView.as_view(template_name="about.html")),
]
Любые аргументы, переданные в as_view() переопределят значения этих же аргументов, указанных в теле класса. В данном примере, мы назначаем атрибут template_name для класса TemplateView. Такой же принцип может быть использован для переопределения атрибута url в классе RedirectView.
Второй, более мощный и гибкий способ использования общих CBV, это использование их в качестве родительских классов. Вы можете указать эти классы в качестве родительских для вашего пользовательского класса-представления и переопределить в теле вашего класса значения атрибутов (таких как 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.conf.urls import url
from some_app.views import AboutView
urlpatterns = [
url(r'^about/', AboutView.as_view()),
]
Для дополнительной информации по использованию общих(generic) представлений-классов, смотрите раздел общие классы-представления.
Предположим, кто-то хочет получить доступ к списку книг в нашей библиотеке, используя для этого HTTP и наши представления в качестве API. Клиент, работающий с API, будет подключаться к сайту и получать данные о книгах с момента последнего визита. Но если новых книг не появилось, то мы сталкиваемся с проблемой непродуктивного расходования времени CPU, создания ненужных запросов к БД: все это лишь с целью того, чтобы вернуть пользователю ответ, “что новых книг нет”. Было бы предпочтительней реализовать в API метод, проверяющий наличие обновлений( дату появления последней новой книги).
В URLconf мы создаем связь URL с представлением, выводящим список книг:
from django.conf.urls import url
from books.views import BookListView
urlpatterns = [
url(r'^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, то ответ(response) будет иметь пустое тело и установленный в нужное значение заголовок Last-Modified, хранящий дату последних изменений в нашей “библиотеке”. Основываясь на этой информации, клиент должен принять решение, нужно или нет получить и скачать полный список объектов.
Mar 31, 2016