Формы и блог с комментариями
Последний шаг к живому блогу — дать посетителям писать. Для приёма и проверки данных в Django есть формы.
Form
from django import forms
class CommentForm(forms.Form):
name = forms.CharField(max_length=50)
email = forms.EmailField(required=False)
text = forms.CharField(min_length=3, max_length=500, widget=forms.Textarea)
Поле формы знает, как проверить значение: CharField (длина, по умолчанию сам убирает пробелы по краям), EmailField, IntegerField(min_value=, max_value=), ChoiceField(choices=…), BooleanField… Все поля обязательны, пока не указано required=False.
form = CommentForm(request.POST)
if form.is_valid():
form.cleaned_data["name"] # очищенное значение нужного типа
else:
form.errors # {"text": ["Убедитесь, что…"], …}
Форма умеет и рисовать себя: {{ form.as_p }} в шаблоне выведет поля с подписями и ошибками.
Свои проверки
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ["title", "text"]
def clean_title(self):
title = self.cleaned_data["title"]
if Post.objects.filter(title__iexact=title).exists():
raise forms.ValidationError("Такой пост уже есть")
return title
clean_<поле>вызывается после встроенных проверок поля;ValidationErrorпревращается в ошибку этого поля;- метод обязан вернуть значение — оно попадёт в
cleaned_data. Забытыйreturn— частая ошибка: значение станетNone; clean(self)без имени поля проверяет поля вместе (например, «пароль и повтор совпадают»).
ModelForm
ModelForm строит поля по модели — не нужно описывать их второй раз. После проверки form.save() создаёт запись (или обновляет, если форма создана с instance=пост).
Обработка формы в представлении
def add_comment(request, pk):
post = get_object_or_404(Post, pk=pk)
form = CommentForm(request.POST)
if not form.is_valid():
return HttpResponse(" ".join(form.errors), status=400)
Comment.objects.create(post=post, **form.cleaned_data)
return redirect("post-detail", pk=post.pk)
После успешной отправки — перенаправление (как во Flask: Post/Redirect/Get). redirect принимает имя маршрута и его аргументы.
В настоящем проекте в настройках включён CsrfViewMiddleware, и в каждую форму добавляют {% csrf_token %} — защиту от отправки формы с чужого сайта.
Что дальше
Вы прошли основы: адреса, шаблоны, модели, связи и формы. Дальше — настоящий проект (django-admin startproject blog), админ-панель django.contrib.admin (её можно получить почти даром), пользователи django.contrib.auth и Django REST Framework для API.
Итог
forms.Form, поля с ограничениями,required=False;is_valid(),cleaned_data,errors;clean_<поле>+ValidationError+ обязательныйreturn;ModelFormиform.save(); после POST —redirect.