Теперь мы рассмотрим класс 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/ к пути:
Попробуем ее изменить, я изменил только поле имени. И нажмем "Обновить статью".
Как мы видим, все прекрасно работает. В следующем разделе мы реализуем возможность редактировать записи только для авторов записей или администраторов сайта.