Чтобы реализовать создание и обновление сущности в CRUD, нужно научиться правильно работать с формами. Создавать формы самостоятельно утомительно. Сотни строк одинакового кода, обработка ошибок, защита от атак — всё это придется делать постоянно.
Обычно у фреймворков есть встроенная поддержка генерации форм. Она состоит из набора функций, которые автоматизируют рутину. Django не является исключением. Он предоставляет ряд инструментов и библиотек, которые помогут создавать формы для отправки пользователем информации, а затем обрабатывать и отвечать на нее. В этом уроке разберем, как генерировать формы.
Django Forms
Формы Django удобны тем, что можно создать новую форму с нуля или воспользоваться ModelForm
, чтобы сохранять содержимое формы в модель.
Django выполняет три отдельные части работы с формами:
- Подготовка данных для рендеринга
- Создание HTML-формы для данных
- Получение и обработка форм и данных от клиента
Для начала работы с формами Django необходимо создать файл forms.py
внутри приложения:
hexlet_django_blog
└── article
└── forms.py
Теперь добавим следующий код:
from django import forms # Импортируем формы Django
class CommentArticleForm(forms.Form):
content = forms.CharField(label='Комментарий') # Текст комментария
В этом примере мы определили класс нашей формы с одним полем — content. Данное описание формы при рендеринге даст следующий HTML-вид:
<label for="id_content">Комментарий:</label>
<textarea name="content" cols="40" rows="10" required id="id_content"></textarea>
Код не включает <form>
тег или кнопку отправки. В дальнейшем нам нужно самим добавить их в шаблон.
Чтобы форма отображалась, нужно создать представление со следующим содержанием:
from django.shortcuts import render
from .forms import CommentArticleForm
class CommentArticleView(View):
def get(self, request, *args, **kwargs):
form = CommentArticleForm() # Создаем экземпляр нашей формы
return render(request, 'comment.html', {'form': form}) # Передаем нашу форму в контексте
Создадим шаблон с нашей формой:
<form action="{% url 'comment_create' %}" method="post">
{% csrf_token %}
<table border="1">
{{ form }}
</table>
<input type="submit" value="Сохранить">
</form>
В шаблоне для отображения формы достаточно указать только {{ form }}
. Дальнейшую генерацию и отображение формы Django возьмет на себя. Мы также обязательно добавляем {% csrf_token %}
в форму. Данная инструкция встраивает скрытое поле со случайным кодом, который проверяется Django и защищает от CSRF-атак.
Обработка Django Forms
Любую информацию о HTTP-запросе и данные формы можно получить из объекта request
. В Django для этого достаточно передать в класс формы request.POST
для автоматической обработки переданных данных:
class CommentArticleView(View):
def post(self, request, *args, **kwargs):
form = CommentArticleForm(request.POST) # Получаем данные формы из запроса
if form.is_valid(): # Проверяем данные формы на корректность
comment = Comment(
name = form.cleaned_data['content'], # Получаем очищенные данные из поля content
# Заполняем оставшиеся поля
)
comment.save()
Django ModelForm
Если в приложении есть база данных, то можно предоставить пользователям возможность заполнения некоторых полей самостоятельно. Например, у нас есть модель ArticleComment и мы хотим создать форму, чтобы пользователи смогли оставлять комментарии
from django.db import models
class ArticleComment(models.Model):
content = models.CharField('content', max_length=100)
В этом случае нам пришлось бы заново определять типы полей для формы. Но это затратно по времени. По этой причине в Django есть вспомогательный класс, который позволяет создавать Form-класс из модели Django
# forms.py
from django.forms import ModelForm
class ArticleCommentForm(ModelForm):
class Meta:
model = ArticleComment
fields = ['content']
Такой класс при генерации будет иметь все перечисленные поля в атрибуте fields
указанной модели в атрибуте model
.
Обработка Django ModelForm
Обработка Django ModelForm отличается от Django Forms только тем, что в ModelForm у нас уже есть связь с моделью. Поэтому мы можем после проверки формы сразу перейти к сохранению данных:
class ArticleCommentFormView(View):
def post(self, request, *args, **kwargs):
form = ArticleCommentForm(request.POST) # Получаем данные формы из запроса
if form.is_valid(): # Проверяем данных формы на корректность
form.save() # Сохраняем форму
Если нам нужно дополнительно заполнить или обработать поля формы, то мы можем указать Django, что данные не нужно сразу сохранять:
class ArticleCommentFormView(View):
def post(self, request, *args, **kwargs):
form = ArticleCommentForm(request.POST) # Получаем данные формы из запроса
if form.is_valid(): # Проверяем данные формы на корректность
comment = form.save(commit=False) # Получаем заполненную модель
# Дополнительно обрабатываем модель
comment.content = check_for_spam(form.data['content'])
comment.save()
В данном примере мы при помощи commit=False
говорим Django, что данные пока сохранять не нужно, и получаем объект нашей модели. После дополнительной обработки модели ее необходимо сохранить с помощью вызова метода .save()
.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.