Обновление очень похоже на создание, но есть одно отличие: мы не создаем сущность с нуля, а извлекаем ее из базы. Остальное практически без изменений.
При этом остается важный вопрос — права на изменение. Изменять что-то на сайте может только автор — кто создал сущность. Механизм, который отвечает за выдачу и проверку прав, называется авторизацией. В Django авторизация встроена. Она не рассматривается в курсе, но про нее можно прочитать самостоятельно в документации.
Форма
Для реализации обновления сущности, нам нужно добавить новые маршрут и обработчик маршрута:
Маршрут
from django.urls import path
from hexlet_django_blog.article.views import IndexView, ArticleFormView, ArticleFormEditView
urlpatterns = [
# ...
path('<int:id>/edit/', ArticleFormEditView.as_view(), name='articles_update'),
]
Важно добавить этот маршрут до маршрута articles/<int:id>/
. Иначе последний перехватит обращение к articles/<int:id>/edit/
, так как он соответствует шаблону.
Обработчик
class ArticleFormEditView(View):
def get(self, request, *args, **kwargs):
article_id = kwargs.get('id')
article = Article.objects.get(id=article_id)
form = ArticleForm(instance=article)
return render(request, 'articles/update.html', {'form': form, 'article_id':article_id})
В данном обработчике мы получаем номер редактируемой статьи. Получаем информацию о записи из базы данных по её id
. Для заполнения формы данными из модели мы применяем дополнительный аргумент instance
класса формы, в который передаем нашу модель с данными.
Шаблон
Шаблон редактирования практически один в один повторяет шаблон создания. Разными у них бывают только отдельные элементы, например, текст кнопки отправки формы. Для таких случаев можно использовать инструкцию include. Она позволяет извлекать общие куски шаблонов в отдельные шаблоны и включать их там где нужно.
{% if form.errors %}
<div>
<ul>
{% for error in form.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'articles_update' id=article_id %}" method="post">
{% csrf_token %}
<table border="1">
{{ form }}
</table>
<input type="submit" value="Сохранить">
</form>
Основных изменений здесь два:
- Другое имя кнопки
- Адрес формы указывает на конкретную статью
Обработчик формы
def post(self, request, *args, **kwargs):
article_id = kwargs.get('id')
article = Article.objects.get(id=article_id)
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
form.save()
return redirect('articles')
return render(request, 'articles/update.html', {'form': form, 'article_id':article_id})
Обработчик, который обновляет сущность, практически идентичен созданию сущности. Только мы работаем с существующей статьей, поэтому ее нужно извлечь из базы данных. Остальное всё то же самое: сохранение и редирект на список статей.
Самостоятельная работа
- Выполните все шаги из теории
- Добавьте в список статей ссылку на редактирование каждой статьи
- Обновите через интерфейс несколько статей. Проверьте работу валидации
- Попробуйте самостоятельно добавить вывод флеш-сообщений
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.