Работа с CreateView. Добавление записей пользователями
Пользователи пишут статьи
До сих пор статьи добавлял только администратор. Дадим эту возможность всем зарегистрированным пользователям.
Форма
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:
- GET — показывает пустую форму (
get_form()→get_context_data()→ рендер). - POST — создаёт форму с
request.POSTиrequest.FILES, вызываетis_valid(). - Если форма валидна —
form_valid(form): сохраняет объект и перенаправляет наget_success_url(). - Если нет —
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
Напишите ArticleCreateForm (ModelForm для Article) с полями title, slug, category,
short_description, full_description, thumbnail, status.
class ArticleCreateForm(forms.ModelForm):
class Meta:
model = Article
fields = ("title", "slug", "category", "short_description", "full_description", "thumbnail", "status")
Напишите ArticleCreateView: только для вошедших (LoginRequiredMixin), наследник CreateView,
модель Article, форма ArticleCreateForm, шаблон blog/articles_create.html.
В form_valid назначьте автора self.request.user (через form.instance.author) и сохраните форму.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
template_name = "blog/articles_create.html"
form_class = ArticleCreateForm
login_url = "home"
def form_valid(self, form):
form.instance.author = self.request.user
form.save()
return super().form_valid(form)
Куда перенаправит CreateView после успешного сохранения, если success_url не указан?
Что делает form_valid() в CreateView по умолчанию?
Добавьте сообщение об успехе с помощью SuccessMessageMixin: класс ArticleCreateView наследует
LoginRequiredMixin, SuccessMessageMixin, CreateView, атрибут success_message = "Статья опубликована".
from django.contrib.messages.views import SuccessMessageMixin
class ArticleCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = Article
form_class = ArticleCreateForm
success_message = "Статья опубликована"
Войдите, чтобы отмечать пройденные уроки.