本文由Scarb发表于金甲虫的博客,转载请注明出处

Django REST framework 自定义分页

需求:在分页结果中返回当前页码、当前每页对象数,对象总数和数据。

DRF默认的分页类型无法实现,于是查看了文档,实现了自定义的分页类型。

1. 设置分页

DRF有两种方式来设置分页,一种是在全局设置中设置分页类型,另一种是对于某个View设置分页类型。

1.1 全局设置分页类型

settings.py中设置DEFAULT_PAGINATION_CLASS,即可对全部的View应用分页。

1
2
3
4
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}

1.2 对某个View设置分页类型

可以对某个View设置分页类型,只要修改pagination_class即可。

1
2
3
4
class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all()
serializer_class = BillingRecordsSerializer
pagination_class = PageNumberPagination

2. 三种DRF框架定义的分页方法

DRF定义了三种分页方法,可以满足大多数需求。

2.1 按照页码分页 PageNumberPagination

Request:

1
GET https://api.example.org/accounts/?page=4

Response:

1
2
3
4
5
6
7
8
9
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [

]
}

配置参数

  • django_paginator_class - The Django Paginator class to use. Default is django.core.paginator.Paginator, which should be fine for most use cases.
  • page_size - A numeric value indicating the page size. If set, this overrides the PAGE_SIZE setting. Defaults to the same value as the PAGE_SIZE settings key.
  • page_query_param - A string value indicating the name of the query parameter to use for the pagination control.
  • 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 to None, 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 if page_size_query_param is also set.
  • last_page_strings - A list or tuple of string values indicating values that may be used with the page_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 to None to disable HTML pagination controls completely. Defaults to "rest_framework/pagination/numbers.html".

2.2 限制偏移量分页 LimitOffsetPagination

Request:

1
GET https://api.example.org/accounts/?limit=100&offset=400

limit表示返回的最大对象数量,相当于其他分页类型的page_size
offset表示查询开始的位置。

1
2
3
4
5
6
7
8
9
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": [

]
}

配置参数

  • default_limit - A numeric value indicating the limit to use if one is not provided by the client in a query parameter. Defaults to the same value as the PAGE_SIZE settings key.
  • limit_query_param - A string value indicating the name of the “limit” query parameter. Defaults to 'limit'.
  • offset_query_param - A string value indicating the name of the “offset” query parameter. Defaults to 'offset'.
  • max_limit - If set this is a numeric value indicating the maximum allowable limit that may be requested by the client. Defaults to None.
  • 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 to None to disable HTML pagination controls completely. Defaults to "rest_framework/pagination/numbers.html".

2.3 游标分页 CursorPagination

提供一个游标,在对象组上移动,只能向前或者向后移动,不支持移动到特定位置。

配置参数

  • page_size = A numeric value indicating the page size. If set, this overrides the PAGE_SIZE setting. Defaults to the same value as the PAGE_SIZE settings key.
  • cursor_query_param = A string value indicating the name of the “cursor” query parameter. Defaults to 'cursor'.
  • ordering = This should be a string, or list of strings, indicating the field against which the cursor based pagination will be applied. For example: ordering = 'slug'. Defaults to -created. This value may also be overridden by using OrderingFilter on the view.
  • 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 to None to disable HTML pagination controls completely. Defaults to "rest_framework/pagination/previous_and_next.html".

3. 自定义分页类型

可以自定义分页类型,这样就可以修改返回的域。

1
2
3
4
5
6
7
8
9
10
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
})

重载get_paginated_response方法,重新定义返回的域和结构。

最后完成了符合需求的分页类型。

1
2
3
4
5
6
7
8
9
10
11
class ScarbPagination(pagination.PageNumberPagination):
page_size = 20
page_size_query_param = 'page_size'

def get_paginated_response(self, data):
return Response(OrderedDict([
('current_page', int(self.request.query_params.get(self.page_query_param, 1))),
('page_size', self.get_page_size(self.request)),
('total_count', self.page.paginator.count),
('data', data)
]))