Pagination
Django提供了一些类来帮助您管理分页数据 - 即分布在多个页面上的数据,使用“上一页/下一页”链接。
REST框架包括对可自定义分页样式的支持。 这允许您修改将大型结果集拆分为单个数据页的方式。
分页API可以支持:
- 分页链接是作为响应内容的一部分提供的。
- 响应头中包含的分页链接,例如
Content-Range
或Link
。
内置样式目前都使用包含在响应内容中的链接。 使用可浏览API时,此样式更易于访问。
只有在使用通用视图或视图集时,才会自动执行分页。 如果您使用常规的APIView
,则需要自己调用分页API以确保返回分页响应。 有关示例,请参阅mixins.ListModelMixin
和generics.GenericAPIView
类的源代码。
可以通过将分页类设置为None
来关闭分页。
Setting the pagination style
可以使用DEFAULT_PAGINATION_CLASS
和PAGE_SIZE
设置键全局设置分页样式。 例如,要使用内置限制/偏移分页,您可以执行以下操作:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
请注意,您需要设置分页类和应该使用的页面大小。 默认情况下,DEFAULT_PAGINATION_CLASS
和PAGE_SIZE
都是None
。
您还可以使用pagination_class
属性在单个视图上设置分页类。 通常,您希望在整个API中使用相同的分页样式,尽管您可能希望基于每个视图改变分页的各个方面,例如默认或最大页面大小。
Modifying the pagination style
如果要修改分页样式的特定方面,则需要覆盖其中一个分页类,并设置要更改的属性。
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
max_page_size = 1000
然后,您可以使用.pagination_class
属性将新样式应用于视图:
class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all()
serializer_class = BillingRecordsSerializer
pagination_class = LargeResultsSetPagination
或者使用DEFAULT_PAGINATION_CLASS
设置键全局应用样式。 For example:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
API Reference
PageNumberPagination
此分页样式在请求查询参数中接受单个数字页码。
Request:
GET https://api.example.org/accounts/?page=4
Response:
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [
…
]
}
Setup
要全局启用PageNumberPagination
样式,请使用以下配置,并根据需要设置PAGE_SIZE
:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
在GenericAPIView
子类上,您还可以设置pagination_class
属性,以基于每个视图选择PageNumberPagination
。
Configuration
PageNumberPagination
类包含许多可以重写以修改分页样式的属性。
要设置这些属性,您应该覆盖PageNumberPagination
类,然后启用上面的自定义分页类。
django_paginator_class
- 要使用的Django Paginator类。 默认值为django.core.paginator.Paginator
,对于大多数用例应该没问题。page_size
- 表示页面大小的数值。 如果设置,则会覆盖PAGE_SIZE
设置。 默认值与PAGE_SIZE
设置键的值相同。page_query_param
- 一个字符串值,指示用于分页控件的查询参数的名称。page_size_query_param
- If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults toNone
, indicating that the client may not control the requested page size.max_page_size
- If set, this is a numeric value indicating the maximum allowable requested page size. This attribute is only valid ifpage_size_query_param
is also set.last_page_strings
- A list or tuple of string values indicating values that may be used with thepage_query_param
to request the final page in the set. Defaults to('last',)
template
- The name of a template to use when rendering pagination controls in the browsable API. May be overridden to modify the rendering style, or set toNone
to disable HTML pagination controls completely. Defaults to"rest_framework/pagination/numbers.html"
.
LimitOffsetPagination
这种分页样式反映了查找多个数据库记录时使用的语法。 客户端包括“限制”和“偏移”查询参数。 限制表示要返回的最大项目数,相当于其他样式中的page_size
。 偏移量表示查询相对于整套未标记项目的起始位置。
Request:
GET https://api.example.org/accounts/?limit=100&offset=400
Response:
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?limit=100&offset=500",
"previous": "https://api.example.org/accounts/?limit=100&offset=300",
"results": [
…
]
}
Setup
要全局启用LimitOffsetPagination
样式,请使用以下配置:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
或者,您也可以设置PAGE_SIZE
键。 如果还使用PAGE_SIZE
参数,那么limit
查询参数将是可选的,客户端可以省略。
在GenericAPIView
子类上,您还可以设置pagination_class
属性,以基于每个视图选择LimitOffsetPagination
。
Configuration
LimitOffsetPagination
类包含许多可以重写以修改分页样式的属性。
要设置这些属性,您应该覆盖LimitOffsetPagination
类,然后启用上面的自定义分页类。
default_limit
- 一个数值,指示客户端在查询参数中未提供限制时使用的限制。 默认值与PAGE_SIZE
设置键的值相同。limit_query_param
- 表示“限制”查询参数名称的字符串值。 Defaults to'limit'
.offset_query_param
- 表示“偏移”查询参数名称的字符串值。 Defaults to'offset'
.max_limit
- 如果设置,这是一个数值,表示客户端可能请求的最大允许限制。 Defaults toNone
.template
- 在可浏览API中呈现分页控件时要使用的模板的名称。 可以重写以修改呈现样式,或设置为None
以完全禁用HTML分页控件。 Defaults to"rest_framework/pagination/numbers.html"
.
CursorPagination
基于光标的分页呈现不透明的“光标”指示符,客户端可以使用该指示符来翻阅结果集。 此分页样式仅显示前向和后退控件,并且不允许客户端导航到任意位置。
基于游标的分页要求结果集中的项具有唯一且不变的排序。 此排序通常可能是记录上的创建时间戳,因为这提供了一致的分页排序。
基于游标的分页比其他方案更复杂。 它还要求结果集呈现固定的排序,并且不允许客户端任意索引到结果集中。 但它确实提供了以下好处:
- 提供一致的分页视图。 正确使用
CursorPagination
确保客户端在分页记录时永远不会看到相同的项目,即使在分页过程中其他客户端插入新项目时也是如此。 - 支持使用非常大的数据集。 对于极大的数据集,使用基于偏移的分页样式的分页可能变得低效或无法使用。 基于游标的分页方案具有固定时间属性,并且不会随着数据集大小的增加而减慢。
Details and limitations
正确使用基于光标的分页需要注意细节。 您需要考虑您希望应用该方案的顺序。 默认是按“ - created”
排序。 这假设在模型实例上必须有一个“创建的”时间戳字段,并且将呈现“时间轴”样式的分页视图,其中最近添加的项目是第一个。
您可以通过覆盖分页类上的'ordering'
属性,或者使用OrderingFilter
过滤器类以及CursorPagination
来修改排序。 与OrderingFilter
一起使用时,您应该强烈考虑限制用户可能订购的字段。
正确使用游标分页应该有一个满足以下条件的排序字段:
- 应该是一个不变的值,例如时间戳,slug或其他仅在创建时设置一次的字段。
- 应该是独特的,或几乎是独一无二的 毫秒精度时间戳就是一个很好的例子。 光标分页的这种实现使用智能“位置加偏移”样式,允许它正确支持非严格唯一值作为排序。
- 应该是一个可以强制转换为字符串的非可空值。
- 不应该是浮动的。 精度错误很容易导致错误的结果。
提示:改用小数。
(如果您已经有一个浮点字段并且必须对其进行分页,则可以使用示例
CursorPagination
子类来使用小数来限制精度。) - 该字段应具有数据库索引。
使用不满足这些约束的排序字段通常仍然有效,但是您将失去光标分页的一些好处。
有关我们用于游标分页的实现的更多技术细节,“Disqus API的构建游标”博客文章概述了基本方法。
Setup
要全局启用CursorPagination
样式,请使用以下配置,根据需要修改PAGE_SIZE
:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 100
}
在GenericAPIView
子类上,您还可以设置pagination_class
属性以基于每个视图选择CursorPagination
。
Configuration
CursorPagination
类包含许多可以重写以修改分页样式的属性。
要设置这些属性,您应该覆盖CursorPagination
类,然后启用上面的自定义分页类。
page_size
=表示页面大小的数值。 如果设置,则会覆盖PAGE_SIZE
设置。 默认值与PAGE_SIZE
设置键的值相同。cursor_query_param
=表示“cursor”查询参数名称的字符串值。 Defaults to'cursor'
.ordering
=这应该是一个字符串或字符串列表,表示将应用基于光标的分页的字段。 For example:ordering = 'slug'
. Defaults to-created
. 也可以通过在视图上使用OrderingFilter
来覆盖此值。template
=在可浏览API中呈现分页控件时要使用的模板的名称。 可以重写以修改呈现样式,或设置为None
以完全禁用HTML分页控件。 Defaults to"rest_framework/pagination/previous_and_next.html"
.
Custom pagination styles
要创建自定义分页序列化程序类,您应该继承pagination.BasePagination
并覆盖paginate_queryset(self,queryset,request,view = None)
和get_paginated_response(self,data)
方法:
paginate_queryset
方法传递给初始查询集,并且应该返回一个只包含所请求页面中的数据的可迭代对象。get_paginated_response
方法传递序列化页面数据,并应返回Response
实例。
请注意,paginate_queryset
方法可以在分页实例上设置状态,稍后可以由get_paginated_response
方法使用该状态。
Example
假设我们想要使用包含嵌套“链接”键下的下一个和上一个链接的修改格式替换默认的分页输出样式。 我们可以像这样指定一个自定义分页类:
class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
},
'count': self.page.paginator.count,
'results': data
})
然后我们需要在配置中设置自定义类:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
'PAGE_SIZE': 100
}
请注意,如果您关心如何在可浏览API的响应中显示键的顺序,则在构造分页响应的主体时可能会选择使用OrderedDict
,但这是可选的。
Using your custom pagination class
要在默认情况下使用自定义分页类,请使用DEFAULT_PAGINATION_CLASS
设置:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
'PAGE_SIZE': 100
}
列表端点的API响应现在将包含Link
标头,而不是将分页链接包含在响应主体的一部分中,例如:
Pagination & schemas
您还可以通过实现get_schema_fields()
方法,使分页控件可用于REST框架提供的模式自动生成。 此方法应具有以下签名:
get_schema_fields(self, view)
该方法应返回coreapi.Field
实例的列表。
A custom pagination style, using the 'Link' header'
HTML pagination controls
默认情况下,使用分页类将导致HTML分页控件显示在可浏览的API中。 有两种内置显示样式。 PageNumberPagination
和LimitOffsetPagination
类显示包含上一个和下一个控件的页码列表。 CursorPagination
类显示更简单的样式,仅显示上一个和下一个控件。
Customizing the controls
您可以覆盖呈现HTML分页控件的模板。 两种内置样式是:
rest_framework/pagination/numbers.html
rest_framework/pagination/previous_and_next.html
Providing a template with either of these paths in a global template directory will override the default rendering for the relevant pagination classes.
Alternatively you can disable HTML pagination controls completely by subclassing on of the existing classes, setting template = None
as an attribute on the class. You'll then need to configure your DEFAULT_PAGINATION_CLASS
settings key to use your custom class as the default pagination style.
Low-level API
用于确定分页类是否应显示控件的低级API在分页实例上公开为display_page_controls
属性。 如果需要显示HTML分页控件,则应在paginate_queryset
方法中将自定义分页类设置为True
。
.to_html()
和.get_html_context()
方法也可以在自定义分页类中重写,以进一步自定义控件的呈现方式。
Third party packages
The following third party packages are also available.
DRF-extensions
The DRF-extensions
package includes a PaginateByMaxMixin
mixin class that allows your API clients to specify ?page_size=max
to obtain the maximum allowed page size.
drf-proxy-pagination
The drf-proxy-pagination
package includes a ProxyPagination
class which allows to choose pagination class with a query parameter.
link-header-pagination
The django-rest-framework-link-header-pagination
package includes a LinkHeaderPagination
class which provides pagination via an HTTP Link
header as desribed in Github's developer documentation.