Django 5 для начинающих

Прогресс по курсу:  9/1004

10.10 Работа с UpdateView. Обновление записей пользователями.
1 из 2 шагов пройден
0 из 3 баллов  получено

Теперь мы рассмотрим класс UpdateView, предназначенный для изменения/обновления текущей статьи в базе данных. Основное отличие класса UpdateView от CreateView, это передача экземпляра изменяемого объекта атрибуту object данного класса, в остальном данные классы идентичны.

Создаем форму для обновления статьи в файле forms.py нашего приложения blog:

class PostUpdateForm(PostCreateForm):
    """
    Форма обновления статьи на сайте
    """

    class Meta:
        model = Post
        fields = PostCreateForm.Meta.fields + ('updater', 'fixed')

    def __init__(self, *args, **kwargs):
        """
        Обновление стилей формы под Bootstrap
        """
        super().__init__(*args, **kwargs)

        self.fields['fixed'].widget.attrs.update({
            'class': 'form-check-input'
        })

Конечно, мы можем использовать форму создания статьи для обновления, но для примера я добавил кнопку фиксации и выбора автора обновления статьи. А так мы наследуемся от существующей формы PostCreateForm, но добавив некоторые поля. В методе __ init__ мы добавили стиль для чек-бокса в форме для поля fixed.

Теперь перейдем к нашим представлениям, добавим новый класс в views.py приложения blog:

from django.views.generic import UpdateView
from .forms import PostUpdateForm


class PostUpdateView(UpdateView):
    """
    Представление: обновления материала на сайте
    """
    model = Post
    template_name = 'blog/post_update.html'
    context_object_name = 'post'
    form_class = PostUpdateForm

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = f'Обновление статьи: {self.object.title}'
        return context

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

Пока мы реализуем возможность при обновлении записей выбирать пользователя, в следующем разделе мы это исправим. И только автор записи сможет редактировать ее.  Также мы переопределили метод проверки формы, form_valid, где закомментировали строку подставления пользователя, который редактирует запись. То есть мы можем убрать из формы PostUpdateForm поле updater и при сохранении записи у нас будет подставляться текущий пользователь.

Для редактирования нам достаточно передать в url первичный ключ или slug изменяемого объекта. Обновляем urls.py для обработки представления обновления:

from django.urls import path
from .views import PostListView, PostDetailView, PostFromCategory, PostCreateView, PostUpdateView

urlpatterns = [
    path('', PostListView.as_view(), name='home'),
    path('post/create/', PostCreateView.as_view(), name='post_create'),
    path('post/<str:slug>/update/', PostUpdateView.as_view(), name='post_update'),
    path('post/<str:slug>/', PostDetailView.as_view(), name='post_detail'),
    path('category/<str:slug>/', PostFromCategory.as_view(), name="post_by_category"),

]

Теперь необходимо добавить HTML шаблон для формы обновления, поэтому создаем в templates/blog файл post_update.html со следующим содержимым:

{% extends 'main.html' %}

{% block content %}
    <div class="card mb-3 border-0 nth-shadow">
        <div class="card-body">
            <div class="card-title nth-card-title">
                <h4>Обновление статьи: {{ post.title }}</h4>
            </div>
            <form method="post" enctype="multipart/form-data">
                {% csrf_token %}
                {{ form.as_p }}
                <div class="d-grid gap-2 d-md-block mt-2">
                    <button type="submit" class="btn btn-dark">Обновить статью</button>
                </div>
            </form>
        </div>
    </div>
{% endblock %}

Можем приступать к тестированию, запустим сервер, авторизуемся в админ панели и перейдем в любую запись. Далее в адресной строке добавим /update/ к пути:

Попробуем ее изменить, я изменил только поле имени. И нажмем "Обновить статью".

Как мы видим, все прекрасно работает. В следующем разделе мы реализуем возможность редактировать записи только для авторов записей или администраторов сайта.


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

А для чего в PostUpdateView мы переопределяем form_valid

def form_valid(self, form):
        form.save()
        return super().form_valid(form)

Если по умолчанию:

?

@Кирилл_Семенихин, В данном случае я просто показал какой метод переопределять в методе UpdateView, чтобы добавить свою логику при сохранении формы. И совсем забыл добавить нужную строку:

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

В form_valid закомментировали строку подставления пользователя, который редактирует запись. То есть мы можем убрать из формы PostUpdateForm поле updater и при сохранении записи у нас будет подставляться текущий пользователь.

Добавил эту информацию в лекцию.