Django 38.2. Добавление, редактирование, удаление поста
В этом посте мы узнаем, что такое миксины в Django, напишем свои, используя наследование создадим представления для страницы добавления и редактирования поста, а также добавим страницу удаления поста.
Все статьи
- 25 Июль 2024 Django 44. Отправка электронной почты в фоновом режиме Комментарии к посту
- 18 Июль 2024 Django 43. Подключаем Celery и Redis для фоновой отправки почты Комментарии к посту
- 06 Июнь 2024 Django 42. Запуск Django-проекта на VPS Комментарии к посту
- 03 Апрель 2024 Django 41. Комментарии к постам Комментарии к посту
- 25 Январь 2024 Django 40. Собственные страницы ошибок Комментарии к посту
- 09 Январь 2024 Django 39. Капча и подтверждение регистрации по email Комментарии к посту
- 19 Декабрь 2023 Django 38.2. Добавление, редактирование, удаление поста Комментарии к посту
- 14 Декабрь 2023 Django 38.1. Кабинет и все посты автора Комментарии к посту
- 28 Ноябрь 2023 Django 37. Две формы - добавление категории и файла Комментарии к посту
- 13 Ноябрь 2023 Django 36. Добавление постов пользователем Комментарии к посту
- 31 Октябрь 2023 Django 35.2. Расширенный профиль пользователя - форма и шаблон Комментарии к посту
- 29 Октябрь 2023 Django 35.1. Расширенный профиль пользователя - модель и сигналы Комментарии к посту
- 25 Октябрь 2023 Django 34.2. Простой профиль пользователя - страница настроек Комментарии к посту
- 23 Октябрь 2023 Django 34.1. Простой профиль пользователя - страница профиля Комментарии к посту
- 20 Октябрь 2023 Django 33. Сброс пароля пользователя Комментарии к посту
- 12 Октябрь 2023 Django 32. Форма регистрации Комментарии к посту
- 09 Октябрь 2023 Django 31. Форма авторизации и кнопка выхода Комментарии к посту
- 29 Сентябрь 2023 Django 30. Рефакторинг и допущенные ошибки Комментарии к посту
- 16 Сентябрь 2023 Django 29.2 Добавляем поиск на сайт, продолжение Комментарии к посту
- 14 Сентябрь 2023 Django 29.1 Добавляем поиск на сайт Комментарии к посту
- 08 Сентябрь 2023 Django 28. Добавляем пагинацию на сайт Комментарии к посту
- 06 Сентябрь 2023 Django 27.2 Представления на основе классов - Практика Комментарии к посту
- 06 Сентябрь 2023 Django 27.1 Представления на основе классов Комментарии к посту
- 06 Сентябрь 2023 Django 26. Контекстные процессоры Комментарии к посту
- 06 Сентябрь 2023 Django 25. Добавляем теги к постам Комментарии к посту
- 06 Сентябрь 2023 Django 24. Связь модели файла и поста Комментарии к посту
- 06 Сентябрь 2023 Django 23. Добавляем sitemap и счётчики Комментарии к посту
- 06 Сентябрь 2023 Django 22. Представление для страницы поста Комментарии к посту
- 05 Сентябрь 2023 Django 21. Регистрация модели поста Комментарии к посту
- 05 Сентябрь 2023 Django 20. Модель поста Комментарии к посту
- 05 Сентябрь 2023 Django 19. Визуальный редактор CKEditor5 Комментарии к посту
- 05 Сентябрь 2023 Django 18. Представление для главной и категорий Комментарии к посту
- 05 Сентябрь 2023 Django 17. Разделение шаблонов Комментарии к посту
- 05 Сентябрь 2023 Django 16. Модель категорий Комментарии к посту
- 05 Сентябрь 2023 Django 15. Пишем API - Добавление пользователя Комментарии к посту
- 05 Сентябрь 2023 Django 14. Модель пользователя бота Комментарии к посту
- 02 Сентябрь 2023 Django 13. Сброс пароля Комментарии к посту
- 02 Сентябрь 2023 Django 12. Настройка отправки почты Комментарии к посту
- 10 Август 2023 Django 11. Пишем API - Обработчик запросов Комментарии к посту
- 10 Август 2023 Django 10. Пишем API - Сериализатор Комментарии к посту
- 08 Август 2023 Django 9. Регистрация модели Комментарии к посту
- 08 Август 2023 Django 8. Первая модель Комментарии к посту
- 03 Август 2023 Django 7. Первое представление Комментарии к посту
- 03 Август 2023 Django 6. Базовый шаблон Комментарии к посту
- 30 Июль 2023 Django 5. Инициализация приложения блога Комментарии к посту
- 27 Июль 2023 Django 4. Суперпользователь и первый запуск Комментарии к посту
- 26 Июль 2023 Django 3. Базовая конфигурация Комментарии к посту
- 26 Июль 2023 Django 2. Создание проекта Комментарии к посту
- 23 Июль 2023 Django 1. Установка Django Комментарии к посту
Дополнительные материалы
Для скачивания материалов необходимо войти или зарегистрироваться
Файлы также можно получить в Telegram-боте по коду: 949621
Реклама
В прошлом посте, мы доработали профиль пользователя, превратив его в кабинет автора. Для этого мы написали свой декоратор и расширили шаблон страницы.
В этом посте мы разберёмся, что такое миксины (mixins), для чего они нужны, как применяются и как написать свои.
Изменим имеющееся представление страницы добавления поста, превратив его в базовый класс, от которого унаследуем два представления: добавления и изменения поста.
Также добавим представление и страницу удаления поста.
Начнём с небольшой теории.
Что такое миксины (mixins)?
Миксины (mixins) представляют собой специальные классы, которые содержат методы и функциональность для повторного использования в других классах. Они используются для организации кода, обеспечивая переиспользование функциональности между различными классами представлений, моделей или других компонентов Django.
Миксины позволяют создавать небольшие модули функциональности, которые могут быть добавлены к классам через множественное наследование. Это позволяет разделить код на более мелкие и переиспользуемые компоненты, что улучшает читаемость, поддержку и уменьшает дублирование кода.
Как работают миксины в Django:
Определение миксина:
Миксин - это обычно класс Python, содержащий методы и атрибуты, предназначенные для использования в других классах. Например:
class MyMixin:
def some_method(self):
# Логика метода
pass
Использование миксина:
Для применения миксина к классу необходимо добавить его в список наследования:
from django.views import View
class MyView(MyMixin, View):
def get(self, request):
# Логика представления
return HttpResponse('Hello, World!')
Здесь MyView
наследуется от MyMixin
и View
. Теперь методы из MyMixin
доступны в MyView
.
Применение миксинов в Django:
- Представления (Views): Миксины могут использоваться для добавления функциональности к представлениям Django, например, для добавления проверок доступа, кэширования или другой логики.
- Модели (Models): Миксины также могут содержать методы для работы с моделями Django, например, для добавления общих методов или свойств к нескольким моделям.
- Формы (Forms): Миксины можно использовать для повторного использования функциональности в формах Django, такой как валидация данных или обработка форм.
- Другие компоненты: Кроме того, миксины можно использовать практически в любом компоненте Django, где требуется повторное использование функциональности.
Важно помнить, что использование миксинов должно быть осторожным, так как слишком много миксинов или их неправильное использование может привести к сложному коду и трудностям в понимании работы приложения.
Собственные миксины.
От теории перейдём к практике и напишем два миксина:
- Миксин проверки принадлежности пользователя к указанной группе.
- Миксин проверки того, что пользователь и автор поста - один человек.
В директории приложения user_app
создадим файл mixins.py
. В нём будем писать наши миксины.
Миксин проверки принадлежности к группе.
Для того, что бы проверять входит ли пользователь в необходимую группу, в данном случае в группу Автор
, можно в каждом представлении прописывать метод dispatch()
с проверкой. Чтобы избежать дублирования кода, мы напишем миксин с проверкой.
Создадим класс PermissionGroupRequiredMixin
.
В нём пропишем поле group_required
и присвоим ему значение None
. Это поле с названием необходимой группы будем прописывать в представлении.
Затем создадим метод dispatch()
. В методе проверяем, входит ли пользователь в указанную группу, то мы вызываем dispatch()
из класса представления. Иначе поднимаем ошибку 403 HttpResponseForbidden
с сообщением об отсутствии доступа.
Код миксина:
from django.http import HttpResponseForbidden
class PermissionGroupRequiredMixin:
group_required = None
def dispatch(self, request, *args, **kwargs):
if request.user.groups.filter(name=self.group_required).exists():
return super().dispatch(request, *args, **kwargs)
else:
raise HttpResponseForbidden("Вы не имеете доступа к этой странице.")
Как видим, достаточно просто.
Миксин проверки автора поста.
Для представлений редактирования и удаления поста, необходима проверка того, что автор поста и текущий пользователь - один человек.
Создадим класс PermissionSameAuthorMixin
.
Код будет такой же, как и предыдущий.
Полей у миксина не будет, а в методе dispatch()
изменим проверку.
Код миксина:
from django.http import HttpResponseForbidden
class PermissionSameAuthorMixin:
def dispatch(self, request, *args, **kwargs):
if request.user self.get_object().author:
return super().dispatch(request, *args, **kwargs)
else:
raise HttpResponseForbidden("Вы не имеете доступа к этой странице.")
Представления.
В директории приложения user_app
откроем файл views.py
.
В посте Django 36. Добавление постов пользователем мы написали следующее представление для страницы добавления поста:
class AddPostByAuthorView(UserPassesTestMixin, CreateView):
template_name = 'user_app/add_post.html'
form_class = forms.AddPostByAuthorForm
model = PostModel
def test_func(self):
return self.request.user.groups.filter(name='Автор').exists()
def get_success_url(self):
return reverse('user_app:user_profile', kwargs={'username': self.request.user.username})
def form_valid(self, form):
form.instance.slug = slugify(form.instance.title)
form.instance.author = self.request.user
return super().form_valid(form)
Мы его изменим, уберём лишнее и создадим два наследуемых класса.
Базовое представление.
Первым делом изменим имя класса на PostByAuthor
, убрав все наследования.
К имеющимся полям добавим новое поле group_required
со значением необходимой для доступа к представлениям группы. В нашем случае группы Автор
.
Удалим метод test_func
, так как он нам больше не нужен.
Всё остальное оставляем как есть. Если IDE будет ругаться на некоторые методы, игнорируем. У нас в классе их нет, но они будут в наших классах наследниках.
Код класса:
from django.urls import reverse_lazy
from pytils.translit import slugify
from blog.models import PostModel
from user_app import forms
class PostByAuthor:
template_name = 'user_app/add_post.html'
group_required = 'Автор'
form_class = forms.AddPostByAuthorForm
model = PostModel
def get_success_url(self):
return reverse('user_app:user_profile', kwargs={'username': self.request.user.username})
def form_valid(self, form):
form.instance.slug = slugify(form.instance.title)[:50]
form.instance.author = self.request.user
return super().form_valid(form)
Представления страниц добавления поста и редактирования поста.
Как вы могли заметить в коде выше, среди полей основного класса мы оставили поле с именем шаблона страницы. Это связано с тем, что для добавления и для редактирования поста будем использовать один и тот же шаблон. Нам нет необходимости создавать второй шаблон, т.к. по содержанию они будут идентичны. Разница лишь в том, что при добавлении поста, поля будут пустыми, а при редактировании они будут заполнены.
Создаём два класса:
AddPostByAuthorView
, унаследованный отPostByAuthor, PermissionGroupRequiredMixin, CreateView
.EditPostByAuthorView
, унаследованный отPostByAuthor, PermissionSameAuthorMixin, UpdateView
.
В первом классе мы наследуемся от нашего основного класса, миксина проверки принадлежности к группе и встроенного класса CreateView
.
Во втором классе мы также наследуемся от основного класса, миксина, проверяющего идентичность автора поста и пользователя, и от стандартного UpdateView
.
В обоих классах добавляем единственное поле extra_context
, в котором прописываем заголовок страницы. Это всё, что будет в двух представлениях.
Код представлений:
from django.views.generic import CreateView, UpdateView
from user_app.mixins import PermissionSameAuthorMixin, PermissionGroupRequiredMixin
class AddPostByAuthorView(PostByAuthor, PermissionGroupRequiredMixin, CreateView):
extra_context = {'title': 'Добавление поста'}
class EditPostByAuthorView(PostByAuthor, PermissionSameAuthorMixin, UpdateView):
extra_context = {'title': 'Изменить пост'}
Представление страницы удаления поста.
Для страницы удаления поста мы напишем отдельное представление.
Создадим класс DeletePostByAuthorView
, унаследованный от PermissionSameAuthorMixin
и DeleteView
.
Прописываем четыре поля:
template_name
- шаблон страницы.model
- модель поста.group_required
- требуемая группа для доступа к странице.extra_context
- дополнительные данные передаваемые в шаблон. В нашем случае заголовок страницы.
Также переопределяем метод get_success_url()
, возвращая на страницу профиля. Он такой же как и в представлениях выше.
Код представления:
from django.views.generic import DeleteView
from django.urls import reverse_lazy
from blog.models import PostModel
from user_app.mixins import PermissionSameAuthorMixin
class DeletePostByAuthorView(PermissionSameAuthorMixin, DeleteView):
template_name = 'user_app/delete_post_confirm.html'
model = PostModel
group_required = 'Автор'
extra_context = {'title': 'Удалить пост?'}
def get_success_url(self):
return reverse_lazy('user_app:user_profile', kwargs={'username': self.request.user.username})
Шаблон страницы удаления поста.
Создадим файл delete_post_confirm.html
в директории с шаблонами.
В шаблоне прописываем форму с двумя кнопками: "подтвердить удаление поста" и "вернуться в профиль".
Код шаблона:
{% extends 'blog/base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="form-section container mt-3">
<h2>Удаление поста {{ object }}</h2>
<p>Вы действительно хотите удалить этот пост?</p>
<form method="POST">
{% csrf_token %}
<button class="btn btn-secondary my-btn-danger me-2" type="submit">Да, удалить</button>
<a href="{% url 'user_app:user_profile' username=request.user.username %}" class="btn btn-primary my-btn-success">Отмена</a>
</form> </div>{% endblock %}
URL-паттерны.
Осталось добавить URL-паттерны
представлений.
Кнопки в кабинете автора мы добавили в прошлом посте.
Откроем файл urls.py
в директории приложения user_app
и добавим следующие строки в список urlpatterns
:
path('post/add_post/', views.AddPostByAuthorView.as_view(), name='add_post'),
path('post/edit_post/<int:pk>', views.EditPostByAuthorView.as_view(), name='edit_post'),
path('post/delete_post/<int:pk>', views.DeletePostByAuthorView.as_view(), name='delete_post'),
Заключение.
В этом посте мы разобрали, что такое миксины. В Django есть ряд встроенных миксинов, таких как LoginRequiredMixin
, проверяющий зарегистрирован пользователь или нет. Написание собственных миксинов поможет расширить функционал представлений, без дублирования кода.
Кроме того, мы ещё раз попробовали создать базовый класс и сделать на его основе представления. Мы сделали один большой класс и два буквально двустрочных
. Если бы мы не сделали базовый класс, у нас вместо трёх, было бы два представления, однако оба были бы идентичными.
Комментарии
-
-
10 сентября 2024 г. 21:10
в шаблоне изменил на
<form method="post" enctype="multipart/form-data" action="{% if form.instance.pk %}{% url 'user_app:edit_post' form.instance.pk %}{% else %}{% url 'user_app:add_post' %}{% endif %}">
и все заработало
paffnik
10 сентября 2024 г. 20:01
Я пытаюсь изменить пост, но вместо этого создается еще одна его копия.
Войдите чтобы добавить комментарий.