9.1 KiB
status, type, tags, created, updated, title, source, aliases
| status | type | tags | created | updated | title | source | aliases | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| processing | concept |
|
2026-05-30 | 2026-06-05 | Django: Работа с формами и CUD |
|
|
Django: Работа с формами и CUD
CUD (Create, Update, Delete) — операции изменения данных: создать, обновить, удалить.
Форма в Django — это слой между HTML-формой и Python-кодом. Она принимает данные от пользователя, проверяет их, приводит к нормальным типам и помогает сохранить результат.
Типы форм
forms.Form— обычная форма, не привязанная к модели. Подходит для поиска, обратной связи, фильтров, отправки email.forms.ModelForm— форма на основе модели. Django сам создаёт поля формы по полям модели и умеет сохранять объект черезform.save().
Если данные не нужно сохранять в таблицу напрямую — чаще подходит forms.Form. Если форма создаёт или редактирует модель — проще использовать forms.ModelForm.
from django import forms
from .models import Blog
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
fields = ["name", "tagline"]
widgets = {
"name": forms.TextInput(attrs={"class": "form-control"})
}
В ModelForm модель и поля задаются во внутреннем классе Meta. fields показывает, какие поля модели попадут в форму. exclude можно использовать наоборот: указать, какие поля не включать.
Жизненный цикл формы в представлении
Обычно view работает так:
- При
GETсоздаёт пустую форму и показывает страницу. - При
POSTсоздаёт форму изrequest.POST. - Проверяет данные через
is_valid(). - Если данные корректные — выполняет действие и делает
redirect. - Если есть ошибки — снова показывает форму с ошибками.
from django.shortcuts import redirect, render
def contact_view(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
data = form.cleaned_data
send_email(data["email"], data["message"])
return redirect("success")
else:
form = ContactForm()
return render(request, "contact.html", {"form": form})
Валидация и очистка данных
is_valid()— запускает проверку формы. После него появляютсяform.cleaned_dataиform.errors.- Автоматическая очистка — Django превращает строки из HTML-формы в Python-типы: число в
int, дату вdate, email в строку после проверки формата. clean_<fieldname>()— проверка одного конкретного поля.clean()— проверка всей формы, когда нужно сравнить несколько полей между собой.
from django import forms
class RegisterForm(forms.Form):
username = forms.CharField(max_length=50)
password = forms.CharField(widget=forms.PasswordInput)
password_repeat = forms.CharField(widget=forms.PasswordInput)
def clean_username(self):
username = self.cleaned_data["username"]
if username.lower() == "admin":
raise forms.ValidationError("Это имя нельзя использовать")
return username
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_repeat = cleaned_data.get("password_repeat")
if password and password_repeat and password != password_repeat:
raise forms.ValidationError("Пароли не совпадают")
return cleaned_data
Для проверки связи между полями используют общий clean(). Например, "Пароль" и "Повтор пароля" нельзя нормально проверить через clean_password(), потому что нужно сравнить два поля.
Generic Editing Views (CBV для CUD)
Django предоставляет готовые классы для типовых страниц редактирования:
CreateView— создать объект.UpdateView— изменить объект; обычно ищет его поpkиз URL.DeleteView— удалить объект; требует подтверждения черезPOST.
Главная идея: вместо ручной обработки GET, POST, is_valid() и save() можно описать модель, форму, шаблон и URL после успеха.
from django.urls import reverse_lazy
from django.views.generic import CreateView, DeleteView, UpdateView
from .forms import BlogForm
from .models import Blog
class BlogCreateView(CreateView):
model = Blog
form_class = BlogForm
template_name = "blog/blog_form.html"
success_url = reverse_lazy("blog_list")
class BlogUpdateView(UpdateView):
model = Blog
form_class = BlogForm
template_name = "blog/blog_form.html"
success_url = reverse_lazy("blog_list")
class BlogDeleteView(DeleteView):
model = Blog
template_name = "blog/blog_confirm_delete.html"
success_url = reverse_lazy("blog_list")
Отображение в шаблоне
{{ form.as_p }}— быстро вывести поля формы в<p>.{{ form.as_table }}— вывести поля как строки таблицы.- Ручное управление нужно, когда важна HTML-разметка, CSS-классы или отдельный вывод ошибок.
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Сохранить</button>
</form>
<form method="post">
{% csrf_token %}
{% for field in form %}
<div>
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
<button type="submit">Сохранить</button>
</form>
CSRF-токен
CSRF (Cross-Site Request Forgery) — атака, при которой чужой сайт пытается отправить запрос от имени уже авторизованного пользователя.
Пример: пользователь залогинен в Django-приложении. Он открывает вредную страницу, а она незаметно отправляет POST-запрос на удаление объекта. Без защиты браузер приложит cookies пользователя, и сервер может принять запрос как настоящий.
{% csrf_token %} добавляет в форму скрытое поле с защитным токеном:
<input type="hidden" name="csrfmiddlewaretoken" value="...">
При POST Django сверяет токен из формы с токеном пользователя. Если токена нет или он неправильный, запрос отклоняется.
Короткое правило: во все HTML-формы с method="post" добавлять {% csrf_token %}.
Простыми словами для экзамена
Форма Django делает три вещи:
- Описывает поля.
- Валидирует входные данные.
- Даёт очищенные данные в
cleaned_data.
Основные поля:
CharField— строка;IntegerField— целое число;BooleanField—True/False;ChoiceField— выбор из списка;EmailField— email;DateField— дата;FileField— файл.
widget управляет HTML-представлением поля, а не типом данных. Например, строковое поле можно показать как пароль:
password = forms.CharField(widget=forms.PasswordInput)
Подсказка к полю задаётся через help_text:
email = forms.EmailField(help_text="Введите рабочую почту")
После form.is_valid():
form.cleaned_dataсодержит нормальные Python-значения;form.errorsсодержит ошибки;form.save()уModelFormсохраняет объект модели.