Files
SecondBrain/90 Library/Programming/Python/Django: Работа с формами и CUD.md
T
2026-05-31 10:23:49 +03:00

7.3 KiB

status, type, tags, created, updated, title, source, aliases
status type tags created updated title source aliases
processing concept
django
forms
crud
validation
modelform
2026-05-30 2026-05-31 Django: Работа с формами и CUD
lec5-django_cud_form.pdf
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"})
        }

Жизненный цикл формы в представлении

Обычно view работает так:

  1. При GET создаёт пустую форму и показывает страницу.
  2. При POST создаёт форму из request.POST.
  3. Проверяет данные через is_valid().
  4. Если данные корректные — выполняет действие и делает redirect.
  5. Если есть ошибки — снова показывает форму с ошибками.
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

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 %}.