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

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

11.1 Создание древовидных комментариев
2 из 2 шагов пройдено

В этом разделе мы рассмотрим создание древовидных комментариев в Django, с использованием библиотеки MPTT.
Так же мы используем JavaScript для динамического добавления комментариев, на странице, без перезагрузки страницы в браузере.

Древовидные комментарии — это организация комментариев в виде иерархической структуры, где каждый комментарий может содержать дочерние комментарии. Такая структура позволяет пользователям оставлять ответы на комментарии других пользователей, создавая дискуссии и подробное обсуждение.

В разделе 10.2 "Создание древовидной модели категорий" мы уже установили библиотеку MPTT для древовидных категорий, для создания комментариев мы будем тоже ее использовать.
 

Создание модели комментариев

Для начала добавим в файл models.py, нашего приложения blog, следующий код:

class Comment(MPTTModel):
    """
    Модель древовидных комментариев
    """

    STATUS_OPTIONS = (
        ('published', 'Опубликовано'),
        ('draft', 'Черновик')
    )

    post = models.ForeignKey(Post, on_delete=models.CASCADE, verbose_name='Запись', related_name='comments')
    author = models.ForeignKey(User, verbose_name='Автор комментария', on_delete=models.CASCADE, related_name='comments_author')
    content = models.TextField(verbose_name='Текст комментария', max_length=3000)
    time_create = models.DateTimeField(verbose_name='Время добавления', auto_now_add=True)
    time_update = models.DateTimeField(verbose_name='Время обновления', auto_now=True)
    status = models.CharField(choices=STATUS_OPTIONS, default='published', verbose_name='Статус поста', max_length=10)
    parent = TreeForeignKey('self', verbose_name='Родительский комментарий', null=True, blank=True, related_name='children', on_delete=models.CASCADE)

    class MTTMeta:
        """
        Сортировка по вложенности
        """
        order_insertion_by = ('-time_create',)

    class Meta:
        """
        Сортировка, название модели в админ панели, таблица в данными
        """
        ordering = ['-time_create']
        verbose_name = 'Комментарий'
        verbose_name_plural = 'Комментарии'

    def __str__(self):
        return f'{self.author}:{self.content}'

С помощью библиотеки MPTT мы создаём древовидную систему комментариев и создаём связь многие-к-одному для модели Post, так как комментарий закрепляется за записью, так же создадим связь с User (автора комментария) моделью.

У модели, созданной с помощью MPTTModel, есть свои мета классы с параметрами, один из них это order_insertion_by - сортировка по вложенности.


Выполним миграции для созданной модели комментариев, с помощью команд:

python manage.py makemigrations
python manage.py migrate

 

Создание формы для создания комментариев

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

from .models import Comment

class CommentCreateForm(forms.ModelForm):
    """
    Форма добавления комментариев к статьям
    """
    parent = forms.IntegerField(widget=forms.HiddenInput, required=False)
    content = forms.CharField(label='', widget=forms.Textarea(
        attrs={'cols': 30, 'rows': 5, 'placeholder': 'Комментарий', 'class': 'form-control'}))

    class Meta:
        model = Comment
        fields = ('content',)

В этом коде мы создаём форму, на основе нашей модели Comment, наследуясь от ModelForm.

Но как вы видите, мы добавили скрытое поле parent для ID родителя. Его будем заполнять с помощью JavaScript


В следующем шаге мы разработаем представления для формы и модели комментариев.


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

Поделюсь - я использовал наследование модели Comment от ActivatorModel и TimeStampedModel из DjangoExtensions, т.к. они реализуют существенную часть полей, которые были добавлены "руками".

Это сработало, пришлось позаботиться только о переименовании поля time_create в created

order_insertion_by = ('-created',)

Ожидал, что придется обрабатывать ситуацию с активными (опубликованными в оригинале) комментариями, но статусы комментариев в этой части курса не используются. Даже если через админку изменить статус в добавленном комментарии на неактивный (черновик), он будет отображаться.

class Comment(ActivatorModel, TimeStampedModel, MPTTModel):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, verbose_name='Запись', related_name='comments')
    author = models.ForeignKey(get_user_model(), verbose_name='Автор комментария',
                               on_delete=models.CASCADE, related_name='comments_author')
    content = models.TextField(verbose_name='Текст комментария', max_length=3000)
    parent = TreeForeignKey('self', verbose_name='Родительский комментарий', null=True, blank=True,
                            related_name='children', on_delete=models.CASCADE)