Класс FormView

Курс по Django: https://stepik.org/a/183363

Архив проекта: 54_sitewomen.zip

Продолжаем изучение классов представлений и затронем следующий из них – это класс FormView. Подробную информацию о нем можно посмотреть по следующей ссылке:

https://docs.djangoproject.com/en/4.2/ref/class-based-views/generic-editing/#formview

Он предназначен для автоматизации отображения и обработки HTML-форм. И, давайте, посмотрим, как его можно применить в нашем учебном проекте.

Ранее мы с вами создавали класс AddPage для отображения формы добавления статей. Но наследовали его от базового класса View. Так вот, правильнее было бы здесь использовать класс FormView. Для этого выше я еще раз сделаю объявление этого класса со следующими атрибутами:

class AddPage(FormView):
    form_class = AddPostForm
    template_name = 'women/addpage.html'
    success_url = reverse('home')

Сам базовый класс расположен в ветке:

from django.views.generic.edit import FormView

(Хотя его формально можно импортировать и из django.views.generic. Он туда импортируется из edit.)

Названия атрибутов класса говорят сами за себя. Первый form_class должен ссылаться на класс формы. Второй template_name – на маршрут к шаблону для отображения формы. Наконец, третий success_url определяет маршрут перенаправления при успешной отправке после валидации формы. Однако, если сейчас попытаться запустить веб-сервер, то увидим сообщения об ошибках. Они связаны с использованием функции reverse(). Она пытается построить маршрут по имени 'home', но этот маршрут на момент формирования класса AddPage не определен. В таких ситуациях следует пользоваться другой аналогичной функцией:

success_url = reverse_lazy('home')

которая также строит маршрут по имени 'home', но не сразу при формировании класса, а в момент, когда он реально понадобится фреймворку Django. Здесь суффикс _lazy означает «ленивый», то есть, маршрут выстраивается лишь в момент его использования, а не заранее. В данном случае это очень важно.

Вообще всегда вместо функции reverse() можно прописывать функцию reverse_lazy(). Тогда ошибок, связанных с отложенным формированием маршрута, возникать не должно. Поэтому на практике довольно часто можно увидеть вызов именно reverse_lazy().

Итак, наш класс в самом простом варианте готов. Если сейчас перейти на страницу добавления статьи:

http://127.0.0.1:8000/addpage/

то заметим, что не хватает главного меню и заголовка страницы. И это не удивительно, так как мы в шаблон не передавали дополнительные параметры. Как это делается, мы уже знаем. Я воспользуюсь атрибутом extra_context:

class AddPage(FormView):
    form_class = AddPostForm
    template_name = 'women/addpage.html'
    success_url = reverse_lazy('home')
    extra_context = {
        'menu': menu,
        'title': 'Добавление статьи',
    }

Теперь страница с формой отображается как и прежде. Попробуем добавить новый пост с произвольными данными, нажимаем кнопку «Добавить» и попадаем на главную страницу. Визуально все отработало, как и задумывалось, но в реальности введенные данные в БД добавлены не были. В этом легко убедиться во вкладке админ-панели со списком статей:

http://127.0.0.1:8000/admin/women/women/

Он не изменился. В действительности, мы с вами лишь реализовали отображение формы с проверкой корректности введенных данных. Например, если ввести неверный слаг, то увидим сообщение от модели формы. То есть, сейчас все работает, кроме сохранения данных. Этот функционал мы должны прописать дополнительно.

Для этого в классе AddPage нужно переопределить специальный метод form_valid(). Например, так:

    def form_valid(self, form):
        form.save()
        return super().form_valid(form)

Этот метод вызывается только после успешной проверки всех переданных данных формы. Параметр form – это ссылка на заполненную форму. Поэтому нам остается только вызвать метод save() и сохранить данные в БД. В конце обязательно нужно записать оператор return с вызовом этого же метода из базового класса.

Так как метод form_valid() вызывается после проверки данных, то в нем доступен словарь form.cleaned_data, который содержит всю корректную переданную информацию, и мы совершенно безопасно здесь можем ее использовать.

Снова заполним форму данными, нажимаем «Добавить» и видим в списке новую запись. Мы полностью повторили функционал предыдущего класса AddPage. Как видите, все достаточно просто. Здесь только нужно учитывать, что объект формы в шаблон addpage.html передается через параметр form. Мы именно его использовали. Если указать любое другое имя, то форма, конечно же, отображаться не будет. На это обращайте внимание.

Курс по Django: https://stepik.org/a/183363

Видео по теме