Работа с CreateView. Добавление записей пользователями

⏱ 25 мин · 🧩 заданий: 5

Пользователи пишут статьи

До сих пор статьи добавлял только администратор. Дадим эту возможность всем зарегистрированным пользователям.

Форма

modules/blog/forms.py:

from django import forms

from .models import Article


class ArticleCreateForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ("title", "slug", "category", "short_description", "full_description", "thumbnail", "status")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields:
            self.fields[field].widget.attrs.update({"class": "form-control", "autocomplete": "off"})
        self.fields["slug"].required = False
        self.fields["slug"].help_text = "Оставьте пустым — заполнится автоматически"

Поле author в форму не включаем: пользователь не должен выбирать автора — им будет тот, кто вошёл. Поле category (TreeForeignKey) отобразится выпадающим списком с отступами по уровням.

CreateView

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView

from .forms import ArticleCreateForm
from .models import Article


class ArticleCreateView(LoginRequiredMixin, CreateView):
    model = Article
    template_name = "blog/articles_create.html"
    form_class = ArticleCreateForm
    login_url = "home"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["title"] = "Добавление статьи на сайт"
        return context

    def form_valid(self, form):
        form.instance.author = self.request.user
        form.save()
        return super().form_valid(form)

Как работает CreateView:

  1. GET — показывает пустую форму (get_form() → get_context_data() → рендер).
  2. POST — создаёт форму с request.POST и request.FILES, вызывает is_valid().
  3. Если форма валидна — form_valid(form): сохраняет объект и перенаправляет на get_success_url().
  4. Если нет — form_invalid(form): снова показывает форму с ошибками.

Мы переопределили form_valid, чтобы до сохранения подставить автора: form.instance — это объект модели, который форма собирается сохранить.

После сохранения пользователь попадёт на get_absolute_url() новой статьи. Другой адрес можно задать атрибутом success_url = reverse_lazy("home").

login_url — куда отправить анонимного пользователя (по умолчанию settings.LOGIN_URL).

Маршрут

path("articles/create/", ArticleCreateView.as_view(), name="articles_create"),
path("articles/<str:slug>/", ArticleDetailView.as_view(), name="articles_detail"),

create/ — выше маршрута со слагом.

Шаблон

templates/blog/articles_create.html:

{% extends "main.html" %}
{% block content %}
  <div class="card">
    <div class="card-body">
      <h1 class="h4">{{ title }}</h1>
      <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.non_field_errors }}
        {% for field in form %}
          <div class="mb-3">
            {{ field.label_tag }}
            {{ field }}
            {% if field.help_text %}<div class="form-text">{{ field.help_text }}</div>{% endif %}
            {% for error in field.errors %}<div class="text-danger small">{{ error }}</div>{% endfor %}
          </div>
        {% endfor %}
        <button type="submit" class="btn btn-primary">Добавить статью</button>
      </form>
    </div>
  </div>
{% endblock %}

Ссылка в шапке для вошедших:

{% if request.user.is_authenticated %}
  <a class="btn btn-success" href="{% url 'articles_create' %}">Добавить статью</a>
{% endif %}

Сообщение об успехе

from django.contrib.messages.views import SuccessMessageMixin


class ArticleCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
    ...
    success_message = "Статья «%(title)s» опубликована"

%(title)s подставит значение поля из cleaned_data.

Итог

  • CreateView = GET (пустая форма) + POST (валидация, сохранение, редирект).
  • Автор подставляется в form_valid() через form.instance.author = self.request.user.
  • LoginRequiredMixin слева закрывает доступ анонимам.
  • После создания — редирект на get_absolute_url() или success_url; сообщение — SuccessMessageMixin.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Написать код

Напишите ArticleCreateForm (ModelForm для Article) с полями title, slug, category, short_description, full_description, thumbnail, status.

Задание 2 Написать код

Напишите ArticleCreateView: только для вошедших (LoginRequiredMixin), наследник CreateView, модель Article, форма ArticleCreateForm, шаблон blog/articles_create.html. В form_valid назначьте автора self.request.user (через form.instance.author) и сохраните форму.

Задание 3 Один вариант ответа

Куда перенаправит CreateView после успешного сохранения, если success_url не указан?

Задание 4 Несколько вариантов

Что делает form_valid() в CreateView по умолчанию?

Задание 5 Написать код

Добавьте сообщение об успехе с помощью SuccessMessageMixin: класс ArticleCreateView наследует LoginRequiredMixin, SuccessMessageMixin, CreateView, атрибут success_message = "Статья опубликована".

Войдите, чтобы отмечать пройденные уроки.