Django 41. Комментарии к постам
В этом посте мы добавим на сайт комментарии к постам.
Все статьи
- 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-боте по коду: 279348
Реклама
В нашем проекте не хватает одного важного элемента – блока комментариев на странице поста. Давайте исправим это.
Что мы сделаем:
- Добавим на страницу поста отображение комментариев.
- Добавим возможность авторизованным пользователям оставлять комментарии.
- Также у автора комментария или администратора должна быть возможность удалить или отредактировать комментарий.
Модель комментария.
Для хранения комментариев нам нужна модель.
Откроем файл models.py
в директории приложения blog
.
Создадим класс CommentModel
, унаследованный от models.Model
, и пропишем четыре поля:
user
– Внешний ключ на модель пользователя.post
– Внешний ключ на модель поста. Для доступа к модели комментария из объекта модели поста указываем аргументrelated_name="comments"
.comment
– Текстовое поле для комментария.created_at
– Поле с датой написания комментария.
Также пропишем внутренний класс Meta
с названием модели и dunder-метод
__str__
с текстовым представлением объекта модели.
Код модели:
class CommentModel(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, verbose_name="Пользователь"
)
post = models.ForeignKey(
PostModel,
on_delete=models.CASCADE,
verbose_name="Пост",
related_name="comments",
)
comment = models.TextField(verbose_name="Комментарий")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Комментарий"
verbose_name_plural = "Комментарии"
def __str__(self):
return f"Комментарий от {self.user} к посту {self.post}"
Регистрация в панели администратора.
Откроем файл admin.py
.
Создадим класс CommentAdmin
, унаследованный от admin.ModelAdmin
. Обернём его в декоратор @admin.register()
, передав в качестве аргумента модель комментария.
Внутри класса поля можно прописать по желанию, например:
list_display
- отображаемые столбцы.list_filter
- выбор по каким полям проводить фильтрацию.
Дополнительно добавим столбец с названием поста при клике на которую будет открываться страница поста.
Для этого создадим метод post_link
, в аргументах он принимает self
и объект модели obj
.
Внутри метода, используя функцию mark_safe
, возвращаем строку со ссылкой.
Затем ниже вызываем метод allow_tags
и устанавливаем его в True
. Это позволит выводить HTML на странице панели администратора.
Не забываем прописать новое поле в list_display
.
Код класса:
@admin.register(models.CommentModel)
class CommentAdmin(admin.ModelAdmin):
list_display = ("user", "post_link", "created_at", "comment")
list_filter = ("user", "post")
def post_link(self, obj):
return mark_safe(
f'<a href="{obj.post.get_absolute_url()}">{obj.post.title}</a>'
)
post_link.allow_tags = True
Форма добавления комментария.
Для того чтобы можно было добавлять новый комментарий, необходима форма модели.
Откроем файл forms.py
и создадим класс CommentForm
, унаследованный от forms.ModelForm
.
Форма будет весьма классическая:
- Определяем поле
comment
. - Прописываем класс
Meta
, указав модель и всего одно поле -comment
.
Код формы:
class CommentForm(forms.ModelForm):
comment = forms.CharField(
widget=forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Введите текст комментария",
"rows": 5
}
),
)
class Meta:
model = CommentModel
fields = ("comment",)
Представления.
Теперь займёмся представлениями. Нам для комментариев нужно три представления:
- Добавление комментария.
- Редактирование.
- Удаление.
Также необходимо изменить представление страницы поста для передачи в него формы комментария.
Представление страницы поста.
Откроем файл views.py
. Найдём класс PostPageView
и добавим метод get_context_data
.
Он тоже весьма стандартный. Внутри метода в контекст добавим новый ключ comment_form
, в который определим объект формы CommentForm
.
Код метода:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["comment_form"] = CommentForm()
return context
Базовое представление.
Нам понадобится три представления, и по сути они идентичны. Различия только в наследуемых классах, поэтому, чтобы избежать дублирования кода, создадим базовый класс BaseCommentView
.
В классе пропишем поле model
, в котором определим класс модели комментария.
И переопределим метод get_success_url
, принимающий только self
.
В нём мы вернём путь до страницы поста.
Код класса:
class BaseCommentView:
model = CommentModel
def get_success_url(self):
post = models.PostModel.objects.get(pk=self.object.post.pk)
return reverse(
"blog:post_page",
kwargs={"category_slug": post.category.slug, "slug": post.slug},
)
Представление добавления комментария.
Создадим класс AddCommentView
, унаследованный от BaseCommentView
и CreateView
, который будет отвечать за добавление комментария.
В нём мы добавим поле form_class
, определив в нём класс формы.
И переопределим метод form_valid
, принимающий self
и объект формы form
.
Поскольку в модель класса требуется передавать пользователя и связанный с комментарием пост, а в форме мы не можем этого сделать, определим их тут.
Внутри метода определяем поля user
и post
, затем вызываем super-метод
для сохранения объекта.
Код представления:
class AddCommentView(BaseCommentView, CreateView):
form_class = CommentForm
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = models.PostModel.objects.get(pk=self.kwargs.get("pk"))
return super().form_valid(form)
Представления редактирования и удаления комментария.
Создадим два класса:
EditCommentView
, унаследованный отBaseCommentView
иUpdateView
.DeleteCommentView
, унаследованный отBaseCommentView
иDeleteView
.
В обоих классах пропишем поле template_name
, в котором пропишем шаблон для страницы редактирования и страницы удаления комментария.
В классе EditCommentView
дополнительно пропишем поле form_class
, как в классе добавления комментария.
Код классов:
class EditCommentView(BaseCommentView, UpdateView):
form_class = CommentForm
template_name = "blog/comment_edit.html"
class DeleteCommentView(BaseCommentView, DeleteView):
template_name = "blog/comment_delete.html"
Маршруты представлений.
Для всех трёх представлений осталось создать маршруты. Для этого откроем файл urls.py
и в список urlpatterns
добавим следующие строки:
path("comment/add/<int:pk>/", views.AddCommentView.as_view(), name="add_comment"),
path(
"comment/edit/<int:pk>/", views.EditCommentView.as_view(), name="edit_comment"
),
path(
"comment/delete/<int:pk>/",
views.DeleteCommentView.as_view(),
name="delete_comment",
),
Шаблоны комментариев.
Начнём с основного шаблона вывода комментариев.
Шаблон добавления и вывода комментариев.
В директории с шаблонами создадим новый файл comments.html
.
В нём пропишем шаблон для отображения комментариев:
<div class="row">
<h2 class="mt-3 mb-3">Добавить комментарий:</h2>
{% if user.is_authenticated %}
<form method="post" enctype="multipart/form-data" action="{% url "blog:add_comment" pk=post.pk %}">
{% csrf_token %}
{{ comment_form.comment }}
<button class="btn btn-outline-warning mt-3" type="submit">Отправить</button>
</form>
{% else %}
<p><a href="{% url 'user_app:login' %}">Войдите</a> чтобы добавить комментарий.</p>
{% endif %}
</div>
<div class="row">
<h2 class="mt-3 mb-3">Комментарии пользователей:</h2>
{% if comments %}
{% for comment in comments %}
<p><a href="{% url 'user_app:user_profile' username=post.author %}">{{ comment.user }}</a>
| {{ comment.created_at }} | {% if comment.user user or user.is_superuser %}
<a href="{% url 'blog:edit_comment' comment.pk %}">Редактировать</a> |
<a href="{% url 'blog:delete_comment' comment.pk %}">Удалить</a>
{% endif %}</p>
<p>{{ comment.comment }}</p>
<hr>
{% endfor %}
{% else %}
<p>Нет комментариев</p>
{% endif %}
</div>
В первом блоке выводим форму для добавления комментария. Обратите внимание, что в форме передаём аргумент action
с маршрутом на представление добавления комментария.
Во втором блоке в цикле выводим комментарии. Также проверяем, что автор комментария – это текущий пользователь или администратор, чтобы отобразить кнопки для редактирования и удаления комментария.
Далее откроем шаблон страницы поста и в удобное место подключим файл шаблона комментариев, передав в него объект поста и список комментариев:
{% include "blog/modules/comments.html" with post=post comments=post.comments.all%}
Шаблон редактирования комментария.
Создадим файл comment_edit.html
и пропишем следующий код:
{% extends 'blog/base.html' %}
{% block title %}Редактирование комментария{% endblock %}
{% block content %}
<div class="form-section container mt-3">
<h2>Редактирование комментария</h2>
<form method="post">
{% csrf_token %}
<p>{{ form.comment }}</p>
<button class="btn btn-primary" type="submit">Обновить</button>
<a href="{% url 'blog:post_page' slug=object.post.slug category_slug=object.post.category.slug %}"
class="btn btn-secondary">Отмена</a>
</form>
</div>
{% endblock %}
Шаблон удаления комментария.
Создадим файл comment_delete.html
и пропишем следующий код:
{% extends 'blog/base.html' %}
{% block title %}Удаление комментария{% endblock %}
{% block content %}
<div class="form-section container mt-3">
<h2>Удаление комментария</h2>
<p>Вы действительно хотите удалить этот комментарий?</p>
<pre>{{ object.comment }}</pre>
<form method="post">
{% csrf_token %}
<button class="btn btn-danger me-2" type="submit">Да, удалить</button>
<a href="{% url 'blog:post_page' slug=object.post.slug category_slug=object.post.category.slug %}"
class="btn btn-secondary">Отмена</a>
</form>
</div>
{% endblock %}
Заключение.
Добавить комментарии несложно. Куда сложнее будет далее за ними следить. Хоть у нас и есть "защита" в виде ограничения на зарегистрированных пользователей, спамеры "не дремлют", и, возможно, в будущем придётся добавлять защиту в виде капчи или что-то другое.
Комментарии
-
-
5 апреля 2024 г. 23:02
Моя ошибка. Обновил файл.
den150v
5 апреля 2024 г. 13:04
Добрый день. Файлы исходного кода при установке говорят: NameError: name 'CreateView' is not defined
Войдите чтобы добавить комментарий.