Создание сущности в CRUD требует наличия двух маршрутов: один для отображения формы, другой — для обработки формы. Также важно понимать, как взаимодействуют между собой эти маршруты, и как обрабатываются ошибки. Начнем с того, что у нас есть три состояния:
- Отображение новой формы
- Отображение формы с подсвеченными ошибками валидации после ее отправки
- Редирект на страницу после успешной обработки формы. Обычно это редактирование сущности или списка сущностей
Самое интересное здесь это когда пользователь нажал кнопку отправки, данные формы приходят в обработчик формы. Этот обработчик выполняет валидацию — проверку введенных данных. Например, проверяет, что данные в принципе есть — они не пустые. Если данные корректные, то обработка завершается, и пользователя отправляют в другое место. Если нет, то Django должен отработать эту ситуацию и сообщить пользователю о неверно введенных данных.
С точки зрения пользователя, сайт снова отображает форму с подставленными значениями, которые он ввел раньше. Кроме этого, на странице выводятся возникшие ошибки. Дальше пользователь их исправляет и отправляет форму заново. Этот процесс может повторяться много раз перед тем, как пользователь сделает все правильно.
Технически Django ведет себя так:
- Пользователь ввел что-то некорректно — происходит редирект на страницу с формой
- Django автоматически записывает данные формы в сессию, а затем использует эти данные для подстановки в форму. Тут участвует
ModelForm
Форма
Для реализации добавления новой сущности, нам нужно добавить четыре составляющие: описание формы, маршрут, обработчик маршрута, шаблон:
Форма
Форма описывает поля существующей модели Article. Поэтому для описания формы воспользуемся вспомогательным классом ModelForm
, чтобы создать Form-класс из модели Django:
from django.forms import ModelForm
from .models import Article
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['name', 'body']
Маршрут
from django.urls import path
from hexlet_django_blog.article.views import IndexView, ArticleFormCreateView
urlpatterns = [
# ...
path('create/', ArticleFormCreateView.as_view(), name='articles_create'),
]
Обработчик
В данном get-обработчике мы создаем объект формы и передаем его в шаблон:
class ArticleFormCreateView(View):
def get(self, request, *args, **kwargs):
form = ArticleForm()
return render(request, 'articles/create.html', {'form': form})
Шаблон
<form action="{% url 'articles_create' %}" method="post">
{% csrf_token %}
<table border="1">
{{ form }}
</table>
<input type="submit" value="Создать">
</form>
Обработчик данных формы
class ArticleFormCreateView(View):
def get(self, request, *args, **kwargs):
# ...
def post(self, request, *args, **kwargs):
form = ArticleForm(request.POST)
if form.is_valid(): # Если данные корректные, то сохраняем данные формы
form.save()
return redirect('articles') # Редирект на указанный маршрут
# Если данные некорректные, то возвращаем человека обратно на страницу с заполненной формой
return render(request, 'articles/create.html', {'form': form})
В данном обработчике нам понадобился доступ к объекту запроса. Любая информация о HTTP-запросе и любые данные, которые отправили по HTTP, можно получить только через request
.
Первым делом объект request
используется в валидации. Валидация в Django привязана к запросу. Она выполняется с помощью метода is_valid()
, который доступен в каждом классе формы.
Метод is_valid()
возвращает true, если данные формы в порядке, и false — в случае ошибок. Если найдены ошибки, то Django сохраняет данные формы и создает словарь ошибок, который можно получить через поле errors
. Самый простой способ вывести ошибки, добавить над формой такой код:
{% if form.errors %}
<div>
<ul>
{% for error in form.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ul>
</div>
{% endif %}
Вернемся к обработчику. Сразу после валидации данные формы сохраняются:
if form.is_valid():
form.save()
Когда объект сохранился в базе данных, осталось перенаправить пользователя в нужное место после успешного создания. Обычно отправка идет на список сущностей или страницу редактирования:
return redirect('articles')
Самостоятельная работа
- Выполните все шаги из теории
- Создайте через интерфейс несколько статей. Проверьте работу валидации
- Попробуйте самостоятельно добавить вывод флеш-сообщений
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.