Class-based Views или Представления, основанные на классах в Django, часть 2

Class-based Views или Представления, основанные на классах в Django, часть 2

Продолжим рассмотрение Class-based views, начатое в прошлой статье. И для начала опять общая информация.

Dispatch

Не только общая, но одна из ключевых. Важной особенностью Class-based views является то, что они могут определять метод HTTP-запроса и изменять поведение в зависимости от метода. Нет, конечно, мы сами тоже можем определить метод, но в Class-based это заложено в основную функциональность. Как же это работает? При срабатывании представления (вызов as_view()) сначала вызывается метод dispatch(), который определяет, какой метод HTTP-запроса был получен, проверяет его на разрешенность, находит правильный обработчик и уже потом вызывает его. Разрешенные методы хранятся в свойстве http_method_names. Это список по умолчанию содержит следующие значения:

Для каждого метода HTTP-запроса, если планируется его обрабатывать, должен быть создан одноименный метод класса. По умолчанию в классе View есть только методы get() и options(). dispatch() работает по следующему алгоритму: получает значение request.method, приводит его к виду строчных букв, находит его сначала в списке http_method_names, потом находит одноименный метод внутри класса и вызывает его. Если метод остутствует или в списке, или в методах класса, то возвращается ответ HttpResponseNotAllowed с ошибкой 405. Спросите, для чего нужен http_method_names, если dispatch() все равно проверяет содержимое класса? Во-первых, на случай, если метод определен (в родителе), но мы его хотим заглушить. Во-вторых, метод options(). В ответ на HTTP-запрос OPTIONS придет список из методов, перечисленных в http_method_names.

Как оформлять непосредственно метод-обработчик? Точно так же, как и классический метод-представление. Только следует не забывать, что он не статический, поэтому первым параметром должен пойти self. Для примера, вышеупомянутый метод options() выглядит так:

FormView

Начнем с FormView. Для начала стоит отметить, что FormView работает преимущественно с классом django.forms.Form, поэтому создадим простую форму (можно создать прямо в файле views.py):

И после уже будем создавать представление. Минимальными полями представления являются следующие: form_class — класс для рендеринга формы (который мы создали), если не заполнить, то вылетит ошибка ‘NoneType’ object is not callable; template_name — имя шаблона, в него передается форма как параметр form, если не указать, то получим TemplateResponseMixin requires either a definition of ‘template_name’; success_url — если не указать, то форма отправится нормально, но после отправки выскочит ошибка No URL to redirect to.

В качестве шаблона создадим файл contact.html со следующим содержанием:

И после этого создадим уже представление:

Это минимальное, что необходимо для работы такого представления.

Чем же можно его расширить? Сначала обратите внимание на методы get_form_class() и, самое главное, get_form(). Это те методы, куда в последствии направляется свойство form_class, действуют по аналогии с другими подобными свойствами. А теперь главная «плюшка», которая появляется только в представлениях для форм — это методы form_valid() и form_invalid(). Вызываются сразу после прохождения или непрохождения формой проверки на валидность соответственно. И если первый метод можно использовать, например, для отправки оповещения (о добавлении нового отзыва, например), то второй метод очень эффективен при использовании кастомных форм авторизации, чтобы фиксировать факты ошибочной авторизации. В основном мануале Django приводится следующий пример:

Заметьте, что в качестве первого параметра в эти методы приходит сам объект формы, так, чтобы внутри можно было спокойно анализировать причину отказа или успеха.

Еще одно свойство/метод, характерные для представлений форм — initial/get_initial(). Это словарь (dict), содержимым которого наполнится форма в момент инициализации (т.е. первого показа, когда её ещё не заполняли)

CreateView, UpdateView и DeleteView

И напоследок смесь из DetailView и FormView. Минимальный набор свойств для этих видов — model для всех и дополнительно success_url для DeleteView.

А теперь про ограничения. Для начала про URL — они конфигурируются так же, как и для DetailView:

Потом про шаблон. По умолчанию имя шаблона будет _form.html (у нас — post_form.html). Так как форма передается в параметр form, то содержимое шаблона для начала можно полностью скопировать из contact.html. И третье — в качестве success_url в CreateView и UpdateView используется get_absolute_url() созданной записи. Поэтому этот метод должен быть определен.

Теперь про плюшки. Большинство наследуется с классов DetailView и FormView. Но есть одна симпатичная, которая появилась только в Django 1.6 — свойство fields. В этом свойстве в виде списка (list) перечисляются имена полей модели, которые будут доступны на форме. Подобное поле есть у класса ModelForm, но если его неудобно использовать, то теперь можно им воспользоваться внутри CreateView и DetailView.

На этом все. В следующей части попробуем рассмотреть микс-ины, как штатные, так и создать свои.

📎📎📎📎📎📎📎📎📎📎