Pagination

2018-07-12  本文已影响0人  YYL07

Django提供了一些类来帮助您管理分页数据 - 即分布在多个页面上的数据,带有“上一页/下一页”链接。

REST框架包括对可自定义分页样式的支持。这允许您修改将大型结果集拆分为单个数据页的方式。
分页API可以支持:

内置样式目前都使用包含在响应内容中的链接。使用可浏览API时,此样式更易于访问。

只有在使用通用视图或视图集时( generic views or viewsets),才会自动执行分页。如果您使用常规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 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类,然后启用上面的自定义分页类。

LimitOffsetPagination

这种分页样式反映了查找多个数据库记录时使用的语法。 客户端包括“limit”和“offset”查询参数。 限制表示要返回的最大项目数,相当于其他样式中的page_size。 偏移量(offset)表示查询相对于整套未标记项目的起始位置。
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类,然后启用上面的自定义分页类。

CursorPagination

基于光标的分页呈现不透明的“光标”指示符,客户端可以使用该指示符来翻阅结果集。 这种分页样式仅呈现正向和反向控件,并且不允许客户端导航到任意位置。

基于游标的分页要求结果集中的项具有唯一且不变的排序。 这种排序通常可以是记录上的创建时间戳,因为这提供了一致的分页排序。

基于游标的分页比其他方案更复杂。 它还要求结果集呈现固定的排序,并且不允许客户端任意索引到结果集中。 但它确实提供了以下好处:

Details and limitations

正确使用基于光标的分页需要注意细节。 您需要考虑您希望应用该方案的顺序。 默认是按“-created”排序。 这假定模型实例上必须存在“已创建”的时间戳字段,并且将呈现“时间轴”样式的分页视图,其中最近添加的项目是第一个。

您可以通过覆盖分页类的“ordering”属性,或者将OrderingFilter过滤器类与CursorPagination一起使用来修改排序。 与OrderingFilter一起使用时,您应该强烈考虑限制用户可能订购的字段。

正确使用游标分页应该有一个满足以下条件的排序字段:

使用不满足这些约束的排序字段通常仍然有效,但是您将失去光标分页的一些好处。

有关我们用于游标分页的实现的更多技术细节,“为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类,然后启用上面的自定义分页类。

Custom pagination styles

要创建自定义分页序列化程序类,您应该继承pagination.BasePagination并覆盖paginate_queryset(self,queryset,request,view = None)和get_paginated_response(self,data)方法:

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响应现在将包含链接头,而不是将分页链接作为响应主体的一部分包括在内,例如:

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分页控件的模板。两种内置样式是:

Low-level API

用于确定分页类是否应显示控件的低级API在分页实例上公开为display_page_controls属性。 如果需要显示HTML分页控件,则应在paginate_queryset方法中将自定义分页类设置为True。

.to_html()和.get_html_context()方法也可以在自定义分页类中重写,以进一步自定义控件的呈现方式。

Third party packages

还提供以下第三方软件包。

DRF-extensions

DRF-extensions软件包包含一个PaginateByMaxMixin mixin类,允许您的API客户端指定?page_size = max以获取允许的最大页面大小。

drf-proxy-pagination

drf-proxy-pagination包中包含一个ProxyPagination类,允许选择带有查询参数的分页类。

link-header-pagination

django-rest-framework-link-header-pagination包中包含一个LinkHeaderPagination类,它通过Github开发者文档中描述的HTTP Link头提供分页。

上一篇 下一篇

猜你喜欢

热点阅读