You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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">&laquo;</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">&raquo;</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

说明

  1. ListView会自动处理分页:当设置paginate_by后,它会自动将查询集分页,并将分页后的对象(包含has_previous、has_next、paginator等属性)放入上下文,对应context_object_name指定的键(这里是posts)。
  2. 原代码中手动创建Paginator并覆盖context['posts'],导致分页对象的属性关联错误,模板无法识别分页状态,因此导航不显示。
  3. 简化后的代码保留了标签上下文的传递,同时利用ListView的内置分页逻辑,无需手动处理分页流程。

内容的提问来源于stack exchange,提问作者Achlys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:13:16