分页器

Django 提供了一些类来帮助你管理分页数据 ——也就是说,数据被分割在几个页面上,并带有 “上一页/下一页” 的链接。这些类位于 django/core/paginator.py 中。

有关示例,请参阅 分页主题指南

Paginator

class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True, error_messages=None)[源代码]

当使用 len() 或直接迭代时,分页器的作用就像一个 Page 的序列。

Paginator.object_list

必要的。一个列表、元组、QuerySet 或其他具有 count()__len__() 方法的可切片对象。为了实现一致的分页,QuerySet 应该是有序的,例如使用 order_by() 子句或使用模型上的默认 ordering

对大型 QuerySet 进行分页的性能问题

如果你使用的 QuerySet 有非常多的项目,在某些数据库上请求高页数可能会很慢,因为产生的 LIMITOFFSET 查询需要计算 OFFSET 记录的数量,随着页数的增加,需要的时间也就越长。

Paginator.per_page

必要的。一个页面中包含的最大项目数,不包括 orphans(参见下面的 orphans 可选参数)。

Paginator.orphans

可选的。当你不希望最后一页的项目数量很少时,使用这个选项。如果最后一页的项目数量通常小于或等于 orphans,那么这些项目将被添加到前一页(成为最后一页),而不是让这些项目单独留在一页上。例如,如果有 23 个条目,per_page=10orphans=3,则会有两页;第一页有 10 个条目,第二页(也是最后一页)有 13 个条目。orphans 默认为 0,这意味着页面永远不会合并,最后一页可能只有一个项目。

Paginator.allow_empty_first_page

可选的。是否允许第一页为空。 如果 False 并且 object_list 是空的,则会出现 EmptyPage 错误。

Paginator.error_messages

New in Django 5.0.

error_messages 参数允许你覆盖分页器将引发的默认消息。传入一个字典,其中的键与你想要覆盖的错误消息相匹配。可用的错误消息键包括:invalid_pagemin_pageno_results

例如,这里是默认的错误消息:

  1. >>> from django.core.paginator import Paginator
  2. >>> paginator = Paginator([1, 2, 3], 2)
  3. >>> paginator.page(5)
  4. Traceback (most recent call last):
  5. ...
  6. EmptyPage: That page contains no results

以下是一个自定义错误消息的示例:

  1. >>> paginator = Paginator(
  2. ... [1, 2, 3],
  3. ... 2,
  4. ... error_messages={"no_results": "Page does not exist"},
  5. ... )
  6. >>> paginator.page(5)
  7. Traceback (most recent call last):
  8. ...
  9. EmptyPage: Page does not exist

方法

Paginator.get_page(number)[源代码]

返回一个给定的基于 1 索引的 Page 对象,同时处理超出范围和无效的页码。

如果页数不是数字,它返回第一页。如果页码为负数或大于页数,则返回最后一页。

只有当你指定了 Paginator(..., allow_empty_first_page=False) 并且 object_list 为空时,才会引发 EmptyPage 异常。

Paginator.page(number)[源代码]

返回一个带有给定的基于 1 的索引的 Page 对象。如果 number 无法通过调用 int() 转换为整数,则引发 PageNotAnInteger。如果给定的页数不存在,则引发 EmptyPage

Paginator.get_elided_page_range(number, *, on_each_side=3, on_ends=2)[源代码]

返回一个基于 1 的页码列表,类似于 Paginator.page_range,但在 Paginator.num_pages 很大时,可能会在当前页码的一侧或两侧添加省略号。

每个当前页码两侧包括的页数由 on_each_side 参数决定,默认为 3。

在页码范围的开头和结尾包括的页数由 on_ends 参数决定,默认为 2。

例如,如果 on_each_sideon_ends 的默认值为,当前页码为 10,总共有 50 页,那么页码范围将是 [1, 2, '…', 7, 8, 9, 10, 11, 12, 13, '…', 49, 50]。这将导致当前页的左侧有页码 7、8 和 9,右侧有页码 11、12 和 13,开头有页码 1 和 2,结尾有页码 49 和 50。

如果给定的页码不存在,则引发 InvalidPage 异常。

属性

Paginator.ELLIPSIS

一个可翻译的字符串,用作 get_elided_page_range() 返回的页面范围中省略的页码的替代物。默认值是 '…'

Paginator.count[源代码]

所有页面的对象总数。

备注

在确定 object_list 中包含的对象数量时,Paginator 将首先尝试调用 object_list.count()。如果 object_list 没有 count() 方法,那么 Paginator 将回到使用 len(object_list)。这允许对象,如 QuerySet,在可用时使用更高效的 count() 方法。

Paginator.num_pages[源代码]

总页数。

Paginator.page_range[源代码]

以 1 为基础的页码范围迭代器,例如产生 [1,2,3,4]

Page

你通常不会手工构建 Page 对象 —— 你将通过迭代 Paginator,或使用 Paginator.page() 获得它们。

class Page(object_list, number, paginator)[源代码]

当使用 len() 或直接迭代时,一个页面就像一个 Page.object_list 的序列。

方法

Page.has_next()[源代码]

如果有下一页,返回 True

Page.has_previous()[源代码]

如果有上一页,返回 True

Page.has_other_pages()[源代码]

如果有下一页 上一页,返回 True

Page.next_page_number()[源代码]

返回下一页的页码。如果下一页不存在,则引发 InvalidPage

Page.previous_page_number()[源代码]

返回上一页的页码。如果上一页不存在,则引发 InvalidPage

Page.start_index()[源代码]

返回页面上第一个对象,相对于分页器列表中所有对象的基于 1 的索引。例如,当对一个有 5 个对象的列表进行分页时,每页有 2 个对象,第二页的 start_index() 将返回 3

Page.end_index()[源代码]

返回页面上最后一个对象相对于分页器列表中所有对象的基于 1 的索引。例如,当对一个有 5 个对象的列表进行分页时,每页有 2 个对象,第二页的 end_index() 将返回 4

属性

Page.object_list

此页上的对象列表。

Page.number

此页的基于 1 的页码。

Page.paginator

关联的 Paginator 对象。

异常

exception InvalidPage[源代码]

当分页器被传递一个无效的页码时引发异常的基类。

Paginator.page() 方法在请求的页面无效(即不是整数)或不包含任何对象时引发异常。一般来说,只要捕获 InvalidPage 异常就够了,但如果你想要更细化,你可以捕获以下任何一种异常。

exception PageNotAnInteger[源代码]

page() 的值不是整数时发生该事件。

exception EmptyPage[源代码]

page() 被赋予一个有效的值,但该页面上没有对象存在时,引发该异常。

这两个异常都是 InvalidPage 的子类,所以你可以用 except InvalidPage 处理这两个异常。