翻译与修改自:Django REST framework — add Custom Pagination

Django REST 框架是用于构建 Web API 的功能强大且灵活的工具包,添加自定义分页很容易。

在开始之前,请确保您已经有一个Django REST 框架项目,如果没有,请阅读 Django REST框架文档 快速 入门

根据 Django REST框架文档,要创建自定义的分页序列化程序类,您应该子类 pagination.BasePagination,重写 paginate_queryset(self, queryset, request, view=None)get_paginated_response(self, data) 方法:

  • paginate_queryset 方法将传递给初始查询集,并且应返回仅包含所请求页面中数据的可迭代对象。
  • get_paginated_response 方法将传递序列化的页面数据,并且应返回一个 Response 实例。

好的,让我们开始吧!

1.添加 pagination.py

在您的项目中创建一个名为 pagination.py 的文件:

[project_name]/
├── [project_name]/
│   ├── __init__.py
│   ├── settings.py      // 这里设置全局默认的分页类
│   ├── urls.py
│   ├── wsgi.py
│   └── pagination.py    <-- 添加这个文件
├── manage.py
├── [app_name]/
│   ├── __init__.py
│   ├── views.py         // 返回自定义分类页的数据

创建一个名为 CustomPagination 的类:

DEFAULT_PAGE = 1
DEFAULT_PAGE_SIZE = 10

class CustomPagination(PageNumberPagination):
    page = DEFAULT_PAGE
    page_size = DEFAULT_PAGE_SIZE
    page_size_query_param = 'page_size'

    def get_paginated_response(self, data):
        return Response({
            'links': {
                'next': self.get_next_link(),
                'previous': self.get_previous_link()
            },
            'total': self.page.paginator.count,
            'page': int(self.request.GET.get('page', DEFAULT_PAGE)), # can not set default = self.page
            'page_size': int(self.request.GET.get('page_size', self.page_size)),
            'results': data
        })
    

2.将自定义分页应用于 views.py

如果要全局使用自定义分页,请将其添加到 settings.py

// settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':    
         '<project_name>.pagination.CustomPagination'
}

或者适用于特定视图

from rest_framework.generics import GenericAPIView
from project_name.pagination import CustomPagination
class XXXView(GenericAPIView):
    queryset = XXX.objects.all()
    serializer_class = XXXSerializer
    pagination_class = CustomPagination <-- 这里

3.如果要获取分页结果并将其添加自定义返回格式中:

from rest_framework.generics import GenericAPIView
from project_name.pagination import CustomPagination

class XXXView(GenericAPIView):
    serializer_class = XXXSerializer
    queryset = XXX.objects.all()
    pagination_class = CustomPagination
    def get(self, request):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            result = self.get_paginated_response(serializer.data)
            data = result.data # pagination data
        else:
            serializer = self.get_serializer(queryset, many=True)
            data = serializer.data
        payload = {
            'return_code': '0000',
            'return_message': 'Success',
            'data': data
        }
        return Response(data)

然后,您可以使用 page 和 page_size 请求视图的URL。这是一个请求后的响应结果示例:

此外,如果您请求的页面无效,则 Django REST 框架可以处理它。它可以节省您的时间来检测参数的类型。