Python Django怎么做分页_内置Paginator分页模块实现大列表数据分块翻页显示

1次阅读

paginator 初始化时 queryset 不能是 list,必须传未求值的 queryset,否则失去数据库分页能力、导致内存溢出;page_obj.Object_list 是切片后结果,不可链式查询;get_page() 比 page() 更安全,自动兜底;模板中应使用 has_other_pages() 判断首尾页显示。

Python Django怎么做分页_内置Paginator分页模块实现大列表数据分块翻页显示

Paginator 初始化时 queryset 不能是 list

直接把 list 传给 Paginator 看似能跑,但会失去数据库分页能力,所有数据提前加载进内存——列表一过万条就卡死或 OOM。
必须传入未求值的 QuerySet,比如 Article.objects.Filter(published=True),而不是 list(Article.objects.filter(...))
常见错误现象:TypeError: object of type 'list' has no len() 或页面响应极慢、内存暴涨。

page_obj.object_list 是当前页数据,不是原始 QuerySet

page_obj.object_list 是已经切片后的结果(QuerySetlist),不能再链式调用 .filter().order_by();想加筛选得在初始化 Paginator 前做完。
使用场景:分页后做前端渲染,或对当前页做轻量处理(如补全关联字段);别试图在 object_list 上再查库。
性能影响:如果误在 object_list 上调用 .count()django 会强制执行 sql,而 Paginator 已经通过 paginator.count 缓存了总数。

get_page() 比 page() 更安全,自动处理非法页码

page() 遇到非数字、负数、超范围页码直接抛 EmptyPagePageNotAninteger 异常,不捕获就会 500;get_page() 则统一返回第一页(1)或最后一页,适合用户直接输 URL 参数的场景。
实操建议:

  • 用户可控的分页入口(如 ?page=xxx)一律用 paginator.get_page(request.GET.get('page'))
  • 后台任务或 API 内部逻辑需精确控制时,才用 page() + try/except
  • 注意 get_page() 返回 None 的情况极少,但若传入 None 或空字符串,它仍会尝试转成 int,失败则回退到第一页

模板里用 page_obj.has_other_pages() 判断要不要显示「首页/末页」按钮

很多人只靠 page_obj.has_previouspage_obj.has_next 控制左右箭头,但漏掉首尾页——尤其当总页数很多时,用户没法快速跳转。
page_obj.has_other_pages() 在总页数 ≤ 1 时返回 False,否则为 True,是判断是否需要渲染「第 1 页」「最后一页」的最简依据。
容易踩的坑:

  • 硬写 {% if page_obj.paginator.num_pages > 3 %} —— 逻辑冗余且和实际 ui 需求脱节
  • page_obj.number == 1 判断是否显示「首页」,但没考虑只有一页时不该显示
  • 忘记给「首页」链接加 ?page=1,导致点完还在当前页

立即学习Python免费学习笔记(深入)”;

分页本身不难,难的是在 queryset 生命周期、异常边界、模板状态之间保持一致——尤其是 get_page() 的“静默兜底”行为,看着省事,但掩盖了参数校验缺失的问题。真要稳,得从 request 入口就明确页码来源和默认值。

text=ZqhQzanResources