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 %}
должны быть помещены в блок , не в тот блок, в который вы выводите комментарии, а в блок, определенный «родительским» шаблоном.