分页-Django REST框架
分页
Django提供了几个类来帮助您管理分页数据--也就是说,数据被分割在几个页面上,并带有“前一个/下一个”链接。
— Django文档
REST框架包括对可自定义分页样式的支持。这允许您修改如何将较大的结果集分割成单独的数据页。
分页API可以支持以下两种方法:
- 作为响应内容的一部分提供的分页链接。
- 包含在响应头中的分页链接,如
Content-Range
或Link
.
内置样式目前都使用作为响应内容一部分的链接。当使用可浏览的API时,这种样式更容易访问。
只有在使用泛型视图或视图集时,分页才会自动执行。如果你用的是普通的APIView
,您需要自己调用分页API,以确保返回分页响应。的源代码mixins.ListModelMixin
和generics.GenericAPIView
类作为示例。
可以通过将分页类设置为None
.
设置分页样式
分页样式可以全局设置,使用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中使用相同的分页样式,尽管您可能希望在每个视图的基础上改变分页的各个方面,例如默认或最大页面大小。
修改分页样式
如果要修改分页样式的特定方面,则需要覆盖一个分页类,并设置要更改的属性。
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
设置键。例如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
}
API参考
PageNumberPagation
此分页样式接受请求查询参数中的单个数字页号。
请求:
GET https://api.example.org/accounts/?page=4
反应:
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [
…
]
}
设置
若要启用PageNumberPagation
样式,使用以下配置,并设置PAGE_SIZE
视需要:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
在……上面GenericAPIView
子类,您也可以设置pagination_class
属性选择PageNumberPagation
在按下浏览的基础上。
配置
这个PageNumberPagation
类包含许多可重写以修改分页样式的属性。
若要设置这些属性,应重写PageNumberPagation
类,然后像上面一样启用自定义分页类。
-
django_paginator_class
-要使用的Django分页器类。默认值是django.core.paginator.Paginator
,这对于大多数用例来说都是可以的。 -
page_size
-表示页码大小的数值。如果设置,则将重写PAGE_SIZE
背景。默认为与PAGE_SIZE
设置键。 -
page_query_param
-一个字符串值,指示要用于分页控件的查询参数的名称。 -
page_size_query_param
-如果设置,这是一个字符串值,指示查询参数的名称,该参数允许客户端在每个请求的基础上设置页面大小。默认为None
,指示客户端可能无法控制请求的页大小。 -
max_page_size
-如果设置,这是一个数字值,指示允许的最大页大小。只有在下列情况下,此属性才有效page_size_query_param
也设置好了。 -
last_page_strings
-字符串值的列表或元组,指示可与page_query_param
若要请求集合中的最后一页,请执行以下操作。默认为('last',)
-
template
-在可浏览API中呈现分页控件时使用的模板的名称。可以重写以修改呈现样式,或将其设置为None
若要完全禁用HTML分页控件,请执行以下操作。默认为"rest_framework/pagination/numbers.html"
.
有限偏移包
这种分页样式反映了查找多个数据库记录时使用的语法。客户端包括一个“限制”和一个“偏移”查询参数。此限制指示要返回的最大项数,并等效于page_size
其他风格的。偏移量指示查询相对于完整的未分页项集的起始位置。
请求:
GET https://api.example.org/accounts/?limit=100&offset=400
反应:
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": [
…
]
}
设置
若要启用有限偏移包
样式全局,使用以下配置:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
也可以选择设置PAGE_SIZE
钥匙。如果PAGE_SIZE
参数,则limit
查询参数是可选的,客户端可以省略。
在……上面GenericAPIView
子类,您也可以设置pagination_class
属性选择有限偏移包
在按下浏览的基础上。
配置
这个有限偏移包
类包含许多可重写以修改分页样式的属性。
若要设置这些属性,应重写有限偏移包
类,然后像上面一样启用自定义分页类。
-
default_limit
-一个数字值,指示如果客户端在查询参数中未提供使用限制。默认为与PAGE_SIZE
设置键。 -
limit_query_param
-一个字符串值,指示“限制”查询参数的名称。默认为'limit'
. -
offset_query_param
-一个字符串值,指示“偏移”查询参数的名称。默认为'offset'
. -
max_limit
-如果设置,这是一个数字值,指示客户端可能请求的最大允许限制。默认为None
. -
template
-在可浏览API中呈现分页控件时使用的模板的名称。可以重写以修改呈现样式,或将其设置为None
若要完全禁用HTML分页控件,请执行以下操作。默认为"rest_framework/pagination/numbers.html"
.
CursorPagation
基于游标的分页显示一个不透明的“游标”指示符,客户端可使用该指示器对结果集进行分页。此分页样式只显示正向和反向控件,不允许客户端导航到任意位置。
基于游标的分页要求在结果集中存在唯一的、不变的项排序。这种排序通常是记录上的创建时间戳,因为这显示了要对其进行分页的一致排序。
基于游标的分页比其他方案更复杂。它还要求结果集呈现固定的排序,并且不允许客户端任意地对结果集进行索引。然而,它确实提供了以下好处:
- 提供一致的分页视图。如果使用得当
CursorPagation
确保客户端在分页记录时不会看到同一项两次,即使在分页过程中其他客户端正在插入新项时也是如此。 - 支持使用非常大的数据集。对于非常大的数据集,使用基于偏移量的分页样式可能会变得低效或不可用。相反,基于光标的分页方案具有固定时间的属性,并且不会随着数据集大小的增加而减慢。
细节和限制
正确使用基于光标的分页需要注意细节。您将需要考虑您希望应用该方案的顺序。默认情况是通过"-created"
...这假设必须有一个“创建”时间戳字段在模型实例上,将显示一个“时间线”样式的分页视图,并首先添加最近添加的项。
可以通过重写'ordering'
属性,或者使用OrderingFilter
过滤器类与CursorPagation
...当与OrderingFilter
您应该强烈考虑限制用户可以订购的字段。
正确使用游标分页应该有一个满足以下条件的排序字段:
- 应该是一个不变的值,例如创建时只设置一次的时间戳、段塞或其他字段。
- 应该是独一无二的,或者几乎是独一无二的。毫秒精度时间戳就是一个很好的例子。这种游标分页的实现使用了一种智能的“位置加偏移量”样式,允许它正确地支持非严格的唯一值作为排序。
- 应该是一个非空值,可以强制使用字符串。
- 不应该是浮子。精度错误容易导致不正确的结果。提示:使用小数代替。(如果您已经有了一个浮动字段,并且必须对其进行分页,则例
CursorPagation
使用小数限制精度的子类在这里可用。.) - 该字段应该有一个数据库索引。
使用不满足这些约束的排序字段通常仍然有效,但是您将失去游标分页的一些好处。
有关我们用于游标分页的实现的更多技术细节,“为Disqus API构建游标”博客文章很好地概述了基本方法。
设置
若要启用CursorPagation
样式,使用以下配置,修改PAGE_SIZE
视需要:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 100
}
在……上面GenericAPIView
子类,您也可以设置pagination_class
属性选择CursorPagation
在按下浏览的基础上。
配置
这个CursorPagation
类包含许多可重写以修改分页样式的属性。
若要设置这些属性,应重写CursorPagation
类,然后像上面一样启用自定义分页类。
-
page_size
=指示页大小的数值。如果设置,则将重写PAGE_SIZE
背景。默认为与PAGE_SIZE
设置键。 -
cursor_query_param
=指示“游标”查询参数名称的字符串值。默认为'cursor'
. -
ordering
=这应该是一个字符串或字符串列表,指示将对其应用基于游标的分页的字段。例如:ordering = 'slug'
...默认为-created
...也可以通过以下方式重写此值:OrderingFilter
在风景上。 -
template
=在可浏览API中呈现分页控件时使用的模板的名称。可以重写以修改呈现样式,或将其设置为None
若要完全禁用HTML分页控件,请执行以下操作。默认为"rest_framework/pagination/previous_and_next.html"
.
自定义分页样式
若要创建自定义分页序列化程序类,应将pagination.BasePagination
并覆盖paginate_queryset(self, queryset, request, view=None)
和get_paginated_response(self, data)
方法:
- 这个
paginate_queryset
方法传递初始查询集,并应返回一个仅包含所请求页中的数据的可迭代对象。 - 这个
get_paginated_response
方法传递序列化的页数据,并应返回反应
举个例子。
注意,paginate_queryset
方法可以在分页实例上设置状态,以后可能由get_paginated_response
方法。
例
假设我们希望用修改后的格式替换默认的分页输出样式,该格式包括嵌套的“链接”键中的下一个链接和前面的链接。我们可以指定一个自定义分页类,如下所示:
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
在构造分页响应的主体时,但这是可选的。
使用自定义分页类
若要默认使用自定义分页类,请使用DEFAULT_PAGINATION_CLASS
背景:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
'PAGE_SIZE': 100
}
列表端点的API响应现在将包括Link
头,而不是将分页链接作为响应主体的一部分,例如:
使用“链接”标题的自定义分页样式
分页与模式
还可以通过实现get_schema_fields()
方法。此方法应具有以下签名:
get_schema_fields(self, view)
方法应该返回coreapi.Field
实例。
HTML分页控件
默认情况下,使用分页类将导致HTML分页控件显示在可浏览的API中。有两种内置的显示样式。这个PageNumberPagation
和有限偏移包
类显示带有上一控件和下一控件的页码列表。这个CursorPagation
类显示一个简单的样式,该样式只显示上一控件和下一控件。
自定义控件
可以重写呈现HTML分页控件的模板。这两种内置风格是:
rest_framework/pagination/numbers.html
rest_framework/pagination/previous_and_next.html
在全局模板目录中提供这些路径之一的模板将覆盖相关分页类的默认呈现。
或者,您可以通过对现有类的子类进行子类化,从而完全禁用HTML分页控件,设置template = None
作为类的属性。然后,您需要配置您的DEFAULT_PAGINATION_CLASS
设置键可将自定义类用作默认分页样式。
低级API
用于确定分页类是否应该显示控件的低级api公开为display_page_controls
属性在分页实例上。应将自定义分页类设置为True
在paginate_queryset
方法,如果它们要求显示HTML分页控件。
这个.to_html()
和.get_html_context()
方法还可以在自定义分页类中重写,以便进一步自定义控件的呈现方式。
第三方包
下面的第三方包也是可用的。
DRF-扩展
这个DRF-扩展
包装包括PaginateByMaxMixin
混合班,它允许您的api客户端指定?page_size=max
若要获得允许的最大页大小,请执行以下操作。
DRF-代理分页
这个DRF-代理分页
包装包括ProxyPagination
类,该类允许使用查询参数选择分页类。
链接头分页
这个django-rest-framework-link-header-pagination
包装包括LinkHeaderPagination
类,它通过HTTP提供分页功能。Link
标题,如GitHub的开发人员文档.
网友评论