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

Django3.2中ListView替换Paginator.page为get_page及使用省略页码范围

修改Django ListView分页实现及添加省略页码范围

替换为Paginator.get_page()

要将ListView默认的Paginator.page()替换为Paginator.get_page(),你需要重写paginate_queryset方法。get_page()会自动处理无效页码(比如非整数、超出总页数的情况),返回第一页或最后一页,而不是抛出错误。

修改后的视图代码如下:

from django.views.generic.list import ListView

class MyList(ListView):
    model = MyModel
    template_name = "template.html"
    paginate_by = 5

    def paginate_queryset(self, queryset, page_size):
        # 获取分页器实例
        paginator = self.get_paginator(
            queryset,
            page_size,
            orphans=self.get_paginate_orphans(),
            allow_empty_first_page=self.get_allow_empty(),
        )
        # 获取当前页码参数
        page_kwarg = self.page_kwarg
        page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
        
        # 使用get_page()替代page()
        page_obj = paginator.get_page(page)
        return (paginator, page_obj, page_obj.object_list, page_obj.has_other_pages())

添加省略页码范围(get_elided_page_range)

要使用get_elided_page_range(),需要在get_context_data方法中将生成的页码范围加入模板上下文,这样就能在模板中渲染截断的页码链接(比如显示1,2,...,5,6,7,...,10,11)。

更新视图,加入get_context_data的重写:

from django.views.generic.list import ListView

class MyList(ListView):
    model = MyModel
    template_name = "template.html"
    paginate_by = 5

    def paginate_queryset(self, queryset, page_size):
        paginator = self.get_paginator(
            queryset,
            page_size,
            orphans=self.get_paginate_orphans(),
            allow_empty_first_page=self.get_allow_empty(),
        )
        page_kwarg = self.page_kwarg
        page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
        
        page_obj = paginator.get_page(page)
        return (paginator, page_obj, page_obj.object_list, page_obj.has_other_pages())

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 如果存在分页,添加省略页码范围到上下文
        if context.get('is_paginated'):
            page_obj = context['page_obj']
            context['elided_page_range'] = page_obj.paginator.get_elided_page_range(
                page_obj.number,
                on_each_side=3,
                on_ends=2
            )
        return context

模板中使用省略页码范围

在你的template.html中,循环elided_page_range来渲染分页链接:

{% if is_paginated %}
  <div class="pagination">
    {% for page_num in elided_page_range %}
      {% if page_num == page_obj.number %}
        <span class="current-page">{{ page_num }}</span>
      {% elif page_num == '...' %}
        <span class="ellipsis">{{ page_num }}</span>
      {% else %}
        <a href="?page={{ page_num }}" class="page-link">{{ page_num }}</a>
      {% endif %}
    {% endfor %}
  </div>
{% endif %}

内容的提问来源于stack exchange,提问作者Daniel Acuña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:40:42