Django DetailView pagination no navigation numbers

(Да, я знаю, что первым предложением будет преобразовать DetailView в ListView; я уже пробовал, и это не помогло)

У меня есть приложение Django forum, его структура - «forum -> subforum -> topic -> comments». Комментарии отображаются на странице связанной с ними темы, поэтому представление темы обрабатывает тему вместе с комментариями. Сама тема включает в себя тему и начальный комментарий (first_comment).

Я просмотрел несколько руководств и вопросов здесь, в SOF, и каким-то образом я заставил свою пагинацию работать в том смысле, что она сокращает количество отображаемых комментариев на число в параметре Paginator (в примере это 5). Но, к сожалению, я не могу воспроизвести никаких ссылок, номеров страниц для навигации по пагинации. И я даже не знаю, где кроется причина этой проблемы - либо в html-коде, либо в коде представления.

Пожалуйста, помогите мне.

Вид:

class ShowTopic(DetailView):
    model = Topic
    template_name = "forum/topic.html"
    slug_url_kwarg = 'topic_slug'
    context_object_name = 'topic'

    def get_context_data(self, **kwargs):
        topic = get_object_or_404(Topic, slug=self.kwargs['topic_slug'])
        comments = self.get_comments(topic)
        comments_number = len(Comment.objects.filter(topic__id=topic.id))
        context = {'menu': menu,
                   'topic': topic,
                   #'comments': comments,
                   'page_obj': comments,
                   'comm_num': comments_number}
        return context

    def get_comments(self, topic):
        qs = Comment.objects.filter(topic=topic)
        paginator = Paginator(qs, 5)
        page = self.request.GET.get('page')
        comments = paginator.get_page(page)
        return comments

topic.html (шаблон темы и комментариев к ней)

urls.py:

from django.urls import path

from forum.views import *


app_name = 'forum'

urlpatterns = [
    path('', SubForumListView.as_view(), name='forum'),
    path('<slug:subforum_slug>/', TopicListView.as_view(), name='subforum'),
    path('<slug:subforum_slug>/add_topic/', AddTopic.as_view(), name="add_topic"),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/', ShowTopic.as_view(), name='topic'),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/add_comment/', AddComment.as_view(), name="add_comment"),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/edit_comment/', UpdateComment.as_view(), name="edit_comment"),
    path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/delete_comment/', DeleteComment.as_view(), name="delete_comment"),
]

Модели тем и комментариев:

class Topic(models.Model):
    subject = models.CharField(verbose_name='Заголовок', max_length=255, unique=True)
    first_comment = models.TextField(verbose_name='Сообщение', max_length=2000, default='')
    slug = models.SlugField(default='', unique=True, max_length=25, editable=False)
    subforum = models.ForeignKey('Subforum',
                                 verbose_name='Раздел',
                                 on_delete=models.CASCADE,
                                 related_name='subforum')
    creator = models.ForeignKey(User,
                                verbose_name='Создатель темы',
                                on_delete=models.SET('deleted'),
                                related_name='creator')
    created = models.DateTimeField(auto_now_add=True)
    closed = models.BooleanField(default=False)
    objects = models.Manager()

    class Meta:
        ordering = ['id']
        verbose_name = 'Обсуждения'
        verbose_name_plural = 'Обсуждения'

    def __str__(self):
        return self.subject

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = f'topic-{slugify(self.subject)}'
            return super(Topic, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('forum:topic', kwargs={'topic_slug': self.slug, 'subforum_slug': self.subforum.slug})


class Comment(models.Model):
    topic = models.ForeignKey('Topic',
                              verbose_name='Тема',
                              on_delete=models.CASCADE,
                              related_name='comments')
    author = models.ForeignKey(User,
                               verbose_name='Комментатор',
                               on_delete=models.SET('deleted'),
                               related_name='author')
    content = models.TextField(verbose_name='Текст', max_length=2000)
    created = models.DateTimeField(verbose_name='Дата публикации', auto_now_add=True)
    updated = models.DateTimeField(verbose_name='Дата изменения', auto_now=True)
    objects = models.Manager()

    class Meta:
        ordering = ['created']
        verbose_name = 'Комментарии'
        verbose_name_plural = 'Комментарии'

    def __str__(self):
        return f'Post of {self.topic.subject} is posted by {self.author.username}.'

{% if is_paginated %} находится вне {% endblock %}, поэтому он будет не рендериться, но даже если бы он был внутри блока, он не будет работать с DetailView, поскольку он не передал его в контекст.

Другая проблема заключается в том, что ваш .get_context_data(…) [Django-doc] не возвращает элементы базового .get_context_data(…), что, по сути, обнуляет его.

Я бы посоветовал работать с ListView:

class ShowTopicView(ListView):
    model = Comment
    template_name = 'forum/topic.html'
    paginate_by = 5

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .filter(topic__slug=self.kwargs['topic_slug'])
        )

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        topic = get_object_or_404(Topic, slug=self.kwargs['topic_slug'])
        context = {**context, 'menu': menu, 'topic': topic}
        return context

и {% if is_paginated %} должны быть помещены в блок , не в тот блок, в который вы выводите комментарии, а в блок, определенный «родительским» шаблоном.

Вернуться на верх