如何在DjangoStarter模板中实现DjangoRestFramework的三种分页策略?

2026-05-19 21:151阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1015个文字,预计阅读时间需要5分钟。

如何在DjangoStarter模板中实现DjangoRestFramework的三种分页策略?

前言:继承Django后端开发系列文章。刚刚遇到一个分页的需求,记录一下。

Django作为全家桶型框架,本身啥都有,分页组件也是有的,但默认的分页组件对API开发并不优化。

前言

继续Django后端开发系列文章。刚好遇到一个分页的需求,就记录一下。

Django作为一个“全家桶”型的框架,本身啥都有,分页组件也是有的,但默认的分页组件没有对API开发做优化,所以DjangoRestFramework这个专门写API的框架又把Django的分页组件包装了一层,集成在viewsets里的时候会更方便。

不过我们不可能一直用viewsets,有一部分API还是要用自由度更高的ApiView的,但ApiView里又没办法直接使用默认的分页组件,这时我们就需要封装一下。

并且DjangoRestFramework默认的分页信息也不够全,比如没有总页数,这点我们也可以在封装的时候魔改一下。

DRF中的分页方式

DRF中为我们封装了三种分页方式,分别是:

  • PageNumberPagination:顾名思义,不解释
  • LimitOffsetPagination:Offset分页
  • CursorPagination:加密分页

本文打算只介绍最常用的第一种,后面两种同时也会做封装,但篇幅关系就不介绍了,有兴趣的同学可以尝试使用一下。

开始代码

首先还是在我们的「DjangoStarter」项目中,在utils目录下新建一个名为paginator的Python Package。

因为代码不多,我们直接写在utils/paginator/__init__.py文件下就好。

from collections import OrderedDict from django.core.paginator import Paginator from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination from rest_framework.response import Response class NumberPaginator(PageNumberPagination): """页码分页""" def __init__( self, page_size, page_size_query_param='page_size', page_query_param='page', max_page_size=None ): """ 初始化分页 :param page_size: 每页显示多少条 :param page_size_query_param: URL中每页显示条数的参数 :param page_query_param: URL中页码的参数 :param max_page_size: 最大页码数限制 """ self.page_size = page_size self.page_size_query_param = page_size_query_param self.page_query_param = page_query_param self.max_page_size = max_page_size def get_paginated_response(self, data): paginator: Paginator = self.page.paginator return Response(OrderedDict([ ('total_item_count', paginator.count), ('page_count', paginator.num_pages), ('page_number', self.page.number), ('page_size', self.page_size), ('next', self.get_next_link()), ('previous', self.get_previous_link()), ('results', data) ])) class LimitOffsetPaginator(LimitOffsetPagination): """Offset分页""" default_limit = 1 limit_query_param = 'limit' offset_query_param = 'offset' max_limit = 999 class CursorPaginator(CursorPagination): """加密分页""" cursor_query_param = 'cursor' page_size = 1 ordering = '-id' # 重写要排序的字段

针对前面说的“DjangoRestFramework默认的分页信息也不够全”问题,我重写了get_paginated_response方法,在返回值中加入这几个参数

  • page_count:总页数
  • page_number:当前页码
  • page_size:每页数量

然后另外两个参数也改了名字,更直观,更符合我们平时的开发习惯。

...

这样就完成了封装,我们接下来在代码里测试一下

测试接口

来写个测试接口看看效果

from utils.paginator import NumberPaginator @swagger_auto_schema( method='get', operation_summary='测试分页功能', manual_parameters=[ openapi.Parameter('page', openapi.IN_QUERY, type=openapi.TYPE_NUMBER), openapi.Parameter('page_size', openapi.IN_QUERY, type=openapi.TYPE_NUMBER), ]) @api_view() def test_page(request): # 测试数据 data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] paginator = NumberPaginator(request.query_params.get('page_size', 10)) return paginator.get_paginated_response({ 'data': paginator.paginate_queryset(queryset=data, request=request) })

配置一下路由

urlpatterns = [ path('test_page', views.test_page), ] 测试效果

写完的接口接受两个参数,pagepage_size,我在@swagger_auto_schema装饰器里声明了这两个参数,方便我们在Swagger文档中做测试。

我们设定page_size=5,拿到的JSON数据是这样的:

{ "message": "请求成功", "code": 200, "data": { "total_item_count": 10, "page_count": 2, "page_number": 1, "page_size": "5", "next": "127.0.0.1:8005/core/test_page?page=2&page_size=5", "previous": null, "results": { "data": [ 1, 2, 3, 4, 5 ] } } }

效果不错,很清晰。

收工。

参考资料
  • www.cnblogs.com/liwenzhou/p/9398959.html
微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。

如何在DjangoStarter模板中实现DjangoRestFramework的三种分页策略?

本文共计1015个文字,预计阅读时间需要5分钟。

如何在DjangoStarter模板中实现DjangoRestFramework的三种分页策略?

前言:继承Django后端开发系列文章。刚刚遇到一个分页的需求,记录一下。

Django作为全家桶型框架,本身啥都有,分页组件也是有的,但默认的分页组件对API开发并不优化。

前言

继续Django后端开发系列文章。刚好遇到一个分页的需求,就记录一下。

Django作为一个“全家桶”型的框架,本身啥都有,分页组件也是有的,但默认的分页组件没有对API开发做优化,所以DjangoRestFramework这个专门写API的框架又把Django的分页组件包装了一层,集成在viewsets里的时候会更方便。

不过我们不可能一直用viewsets,有一部分API还是要用自由度更高的ApiView的,但ApiView里又没办法直接使用默认的分页组件,这时我们就需要封装一下。

并且DjangoRestFramework默认的分页信息也不够全,比如没有总页数,这点我们也可以在封装的时候魔改一下。

DRF中的分页方式

DRF中为我们封装了三种分页方式,分别是:

  • PageNumberPagination:顾名思义,不解释
  • LimitOffsetPagination:Offset分页
  • CursorPagination:加密分页

本文打算只介绍最常用的第一种,后面两种同时也会做封装,但篇幅关系就不介绍了,有兴趣的同学可以尝试使用一下。

开始代码

首先还是在我们的「DjangoStarter」项目中,在utils目录下新建一个名为paginator的Python Package。

因为代码不多,我们直接写在utils/paginator/__init__.py文件下就好。

from collections import OrderedDict from django.core.paginator import Paginator from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination from rest_framework.response import Response class NumberPaginator(PageNumberPagination): """页码分页""" def __init__( self, page_size, page_size_query_param='page_size', page_query_param='page', max_page_size=None ): """ 初始化分页 :param page_size: 每页显示多少条 :param page_size_query_param: URL中每页显示条数的参数 :param page_query_param: URL中页码的参数 :param max_page_size: 最大页码数限制 """ self.page_size = page_size self.page_size_query_param = page_size_query_param self.page_query_param = page_query_param self.max_page_size = max_page_size def get_paginated_response(self, data): paginator: Paginator = self.page.paginator return Response(OrderedDict([ ('total_item_count', paginator.count), ('page_count', paginator.num_pages), ('page_number', self.page.number), ('page_size', self.page_size), ('next', self.get_next_link()), ('previous', self.get_previous_link()), ('results', data) ])) class LimitOffsetPaginator(LimitOffsetPagination): """Offset分页""" default_limit = 1 limit_query_param = 'limit' offset_query_param = 'offset' max_limit = 999 class CursorPaginator(CursorPagination): """加密分页""" cursor_query_param = 'cursor' page_size = 1 ordering = '-id' # 重写要排序的字段

针对前面说的“DjangoRestFramework默认的分页信息也不够全”问题,我重写了get_paginated_response方法,在返回值中加入这几个参数

  • page_count:总页数
  • page_number:当前页码
  • page_size:每页数量

然后另外两个参数也改了名字,更直观,更符合我们平时的开发习惯。

...

这样就完成了封装,我们接下来在代码里测试一下

测试接口

来写个测试接口看看效果

from utils.paginator import NumberPaginator @swagger_auto_schema( method='get', operation_summary='测试分页功能', manual_parameters=[ openapi.Parameter('page', openapi.IN_QUERY, type=openapi.TYPE_NUMBER), openapi.Parameter('page_size', openapi.IN_QUERY, type=openapi.TYPE_NUMBER), ]) @api_view() def test_page(request): # 测试数据 data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] paginator = NumberPaginator(request.query_params.get('page_size', 10)) return paginator.get_paginated_response({ 'data': paginator.paginate_queryset(queryset=data, request=request) })

配置一下路由

urlpatterns = [ path('test_page', views.test_page), ] 测试效果

写完的接口接受两个参数,pagepage_size,我在@swagger_auto_schema装饰器里声明了这两个参数,方便我们在Swagger文档中做测试。

我们设定page_size=5,拿到的JSON数据是这样的:

{ "message": "请求成功", "code": 200, "data": { "total_item_count": 10, "page_count": 2, "page_number": 1, "page_size": "5", "next": "127.0.0.1:8005/core/test_page?page=2&page_size=5", "previous": null, "results": { "data": [ 1, 2, 3, 4, 5 ] } } }

效果不错,很清晰。

收工。

参考资料
  • www.cnblogs.com/liwenzhou/p/9398959.html
微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。

如何在DjangoStarter模板中实现DjangoRestFramework的三种分页策略?