前言

继续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": "http://127.0.0.1:8005/core/test_page?page=2&page_size=5",
"previous": null,
"results": {
"data": [
1,
2,
3,
4,
5
]
}
}
}

效果不错,很清晰。

收工。

参考资料

DjangoRestFramework框架三种分页功能的实现 - 在DjangoStarter项目模板中封装的更多相关文章

  1. Asp.Net中的三种分页方式

    Asp.Net中的三种分页方式 通常分页有3种方法,分别是asp.net自带的数据显示空间如GridView等自带的分页,第三方分页控件如aspnetpager,存储过程分页等. 第一种:使用Grid ...

  2. 带分页功能的SSH整合,DAO层经典封装

    任何一个封装讲究的是,使用,多状态.Action:     任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...

  3. 命令stat anaconda-ks.cfg会显示出文件的三种时间状态(已加粗):Access、Modify、Change。这三种时间的区别将在下面的touch命令中详细详解:

    7.stat命令 stat命令用于查看文件的具体存储信息和时间等信息,格式为"stat 文件名称". stat命令可以用于查看文件的存储信息和时间等信息,命令stat anacon ...

  4. AIR32F103(三) Linux环境基于标准外设库的项目模板

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...

  5. Sql三种分页方法

    --分页三种方法--第一种 ROW_NUMBER() OVER( ORDER BY OrgID) AS indexs 大于pagesize*pageindex,少于等于pagesize*(pagein ...

  6. sqlserver三种分页方式性能比较

    Liwu_Items表,CreateTime列建立聚集索引 第一种,sqlserver2005特有的分页语法 declare @page intdeclare @pagesize intset @pa ...

  7. T-sql中的三种分页查询

    USE [APS_Future_FT] GO /****** Object: StoredProcedure [dbo].[A_PagingAndSorting] Script Date: 2013/ ...

  8. Asp.Net中的三种分页方式总结

    本人ASP.net初学,网上找了一些分页的资料,看到这篇文章,没看到作者在名字,我转了你的文章,只为我可以用的时候方便查看,2010的文章了,不知道这技术是否过期. 以下才是正文 通常分页有3种方法, ...

  9. 获取class对象的三种方法以及通过Class对象获取某个类中变量,方法,访问成员

    public class ReflexAndClass { public static void main(String[] args) throws Exception { /** * 获取Clas ...

随机推荐

  1. ActiveMQ-5.9-笔记-02

  2. collections 数据类型扩展模块

    在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict.namedtuple和Ord ...

  3. 自定义 Django admin 组件

    摘要:学习 Django admin 组件,仿照源码的逻辑,自定义了一个简易的 stark 组件,实现类似 admin 的功能. 可自动生成 url 路由,对于model 有与之相应的配置类对象,可进 ...

  4. [xnuca](web)xblog

    session会话机制介绍如下 http是无状态协议.服务器靠cookie和session来记住用户.$_SESSION 和 $_GET等一样,是超全局变量. 后台脚本里面会写: session() ...

  5. 【推理引擎】ONNX 模型解析

    定义模型结构 首先使用 PyTorch 定义一个简单的网络模型: class ConvBnReluBlock(nn.Module): def __init__(self) -> None: su ...

  6. 半吊子菜鸟学Web开发1 --配置开发环境

    先说说我自己的情况,我算是一个半吊子菜鸟,对web开发熟练度为0,但是对熟悉C++和Python 所以这里开始记录我学习Web开发的历程,看看我这里学习的程序,能够学到什么地方. 首先是配置环境,我的 ...

  7. 面试问题之计算机网络:HTTP和HTTPS的区别

    https://blog.csdn.net/qq_38289815/article/details/80969419

  8. 一个 Spring Bean 定义 包含什么?

    一个Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖.

  9. 数据库中的ACID

    参考链接:什么是ACID 数据库中的锁机制

  10. Memcached 服务分布式集群如何实现?

    特殊说明:Memcached 集群和 web 服务集群是不一样的,所有 Memcached 的数据总和才是数据库的数据.每台 Memcached 都是部分数据.(一台 memcached 的数据,就是 ...