Django标签文章页分页异常:仅显示指定数量无翻页控件
Django标签文章页分页导航不显示问题
问题背景
我开发了一个Django应用,通过内置admin界面创建文章,使用django-taggit为文章添加标签。首页(home.html)可展示文章和标签,点击标签会进入对应标签文章页(tag_posts.html),比如点击'apple'标签会显示所有带该标签的文章。首页及分页功能均正常,但标签文章页仅按paginate_by指定数量(当前为2)显示文章,却无上一页/下一页或页码翻页选项。
已尝试的解决方法
- 怀疑是HTML中的Bootstrap导航链接问题,但该代码与首页正常使用的一致;
- 重构基于类的视图
TagPostsView,将标签作为上下文变量传入模板; - 使用基础HTML实现导航链接。
相关代码
views.py
from django.shortcuts import get_object_or_404, render from django.http import HttpResponse from django.views.generic import ListView, TemplateView from .models import Session, PostsInSession from django.core.paginator import Paginator from taggit.models import Tag class PostView(ListView): queryset = Session.objects.prefetch_related('postsinsession_set').all() context_object_name = 'sessions' template_name = 'home.html' paginate_by = 2 # Number of items per page def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) tags = Tag.objects.order_by('name') paginator = Paginator(self.queryset, self.paginate_by) page = self.request.GET.get('page') sessions = paginator.get_page(page) context['sessions'] = sessions context['tags'] = tags return context class TagPostsView(ListView): template_name = 'tag_posts.html' context_object_name = 'posts' paginate_by = 2 def get_queryset(self): tag_slug = self.get_tag_slug() posts = PostsInSession.objects.filter(post__tags__slug=tag_slug) return posts def get_tag_slug(self): return self.kwargs['tag_slug'] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) tag_slug = self.get_tag_slug() tag = get_object_or_404(Tag, slug=tag_slug) paginator = Paginator(context['posts'], self.paginate_by) page = self.request.GET.get('page') paginated_posts = paginator.get_page(page) context['tag'] = tag context['posts'] = paginated_posts return context
tag_posts.html
{% extends "base.html" %} {% load markdownify %} {% block content %} <div class="row"> <div class="col"> <br> {% if tag %} <h2>Tag: {{ tag.name }}</h2> {% endif %} <hr> {% for post in posts %} <div class="card m-3 text-center"> <div class="card-header"> {{ post.post.title }} </div> <div class="card-body"> {{ post.post.body|markdownify }} </div> </div> {% endfor %} <nav aria-label="Page navigation"> <ul class="pagination justify-content-center"> {% if posts.has_previous %} <li class="page-item"> <a class="page-link" href="?page={{ posts.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% endif %} {% for num in posts.paginator.page_range %} {% if posts.number == num %} <li class="page-item active" aria-current="page"> <span class="page-link">{{ num }}</span> </li> {% else %} <li class="page-item"> <a class="page-link" href="?page={{ num }}">{{ num }}</a> </li> {% endif %} {% endfor %} {% if posts.has_next %} <li class="page-item"> <a class="page-link" href="?page={{ posts.next_page_number }}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> {% endif %} </ul> </nav> </div> </div> {% endblock %}
问题原因及解决方案
核心问题
TagPostsView中手动重新实例化了Paginator,覆盖了ListView自动生成的分页上下文,导致模板中posts.paginator等分页属性无法正确工作。ListView本身已经内置了分页逻辑,无需手动调用Paginator。
修复后的TagPostsView
修改get_context_data方法,移除手动分页的代码,直接使用ListView提供的分页上下文:
class TagPostsView(ListView): template_name = 'tag_posts.html' context_object_name = 'posts' paginate_by = 2 def get_queryset(self): tag_slug = self.kwargs['tag_slug'] return PostsInSession.objects.filter(post__tags__slug=tag_slug) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) tag_slug = self.kwargs['tag_slug'] context['tag'] = get_object_or_404(Tag, slug=tag_slug) return context
说明
- ListView会自动处理分页:当设置
paginate_by后,它会自动将查询集分页,并将分页后的对象(包含has_previous、has_next、paginator等属性)放入上下文,对应context_object_name指定的键(这里是posts)。 - 原代码中手动创建
Paginator并覆盖context['posts'],导致分页对象的属性关联错误,模板无法识别分页状态,因此导航不显示。 - 简化后的代码保留了标签上下文的传递,同时利用ListView的内置分页逻辑,无需手动处理分页流程。
内容的提问来源于stack exchange,提问作者Achlys
相关产品推荐
相关产品推荐

