• python测试开发django-rest-framework-87.分页查询之偏移分页(LimitOffsetPagination)和游标分页(CursorPagination)


    前言

    django-rest-framework 分页器提供了3中分页方式,前面一篇介绍了简单分页 (PageNumberPagination),
    本篇继续介绍另外2个分页偏移分页 (LimitOffsetPagination) 和游标分页 (CursorPagination)

    偏移分页 (LimitOffsetPagination)

    LimitOffsetPagination 是偏移分页,查询的时候url地址带上 limit 和 offset 2个参数,如下格式

    http://localhost:8000/api/v1/goods?limit=100&offset=10

    可以重写 LimitOffsetPagination 类,定义查询的一些参数配置

    • default_limit = api_settings.PAGE_SIZE # 默认条数
    • limit_query_param = 'limit' # 查询时,查询参数及指定查询多少条
    • offset_query_param = 'offset' # 查询时,指定的起始位置是哪
    • max_limit = None # 查询时,最多返回多少条

    先导入LimitOffsetPagination

    # 分页器  -- 偏移分页
    from rest_framework.pagination import LimitOffsetPagination
    
    class MyLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 5               # 设置每页显示的数量为5,那么查询结果默认返回5条
        limit_query_param = 'limit'     # 优先使用limit_query_param来设置显示条数
        offset_query_param = 'offset'   # 偏移数,查询时,指定的起始位置是哪
        max_limit = 20                  # 查询时,最多返回多少条
    
    

    APIView使用分页查询

    写查询视图的时候,先序列化,再定义分页器,查询的时候可以带上参数/api/v1/goods?limit=100&offset=10

    from rest_framework import serializers
    from .models import Goods
    from rest_framework.pagination import PageNumberPagination
    from rest_framework.permissions import IsAuthenticated, AllowAny
    # 作者-上海悠悠 QQ交流群:717225969
    # blog地址 https://www.cnblogs.com/yoyoketang/
    
    
    # 序列化 Goods 模型
    class GoodsAPISerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Goods
            fields = '__all__'  # 返回全部的字段
    
    # 分页器  -- 偏移分页
    class MyLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 5               # 设置每页显示的数量为5,那么查询结果默认返回5条
        limit_query_param = 'limit'     # 优先使用limit_query_param来设置显示条数
        offset_query_param = 'offset'   # 偏移数,查询时,指定的起始位置是哪
        max_limit = 20                  # 查询时,最多返回多少条
    
    
    
    # 查询视图
    class GoodsAPISView(APIView):
        permission_classes = (AllowAny,)      # AllowAny 允许所有用户
    
    
        def get(self, request, *args, **kwargs):
            '''返回所有的'''
            page = MyLimitOffsetPagination()
            goods = Goods.objects.all()   # 查询全部
            ret = page.paginate_queryset(goods, request)
            serializer = GoodsAPISerializer2(ret, many=True)
      
            return Response({
                "code": 0,
                "msg": "success!",
                "data": serializer.data
            })
    
    

    如果我们访问http://localhost:8000/api/v1/goods?offset=10&limit=3那么就是从查询的结果里面第10条数据往后面取3条数据

    {
    	"code": 0,
    	"msg": "success!",
    	"data": [{
    		"id": 109,
    		"create_time": "2021-01-17 10:14:41",
    		"update_time": "2021-01-17 10:14:41",
    		"goodsname": "pytest入门到精",
    		"goodscode": "sp_100010",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 68.8,
    		"stock": 10000,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}, {
    		"id": 110,
    		"create_time": "2021-01-17 10:15:44",
    		"update_time": "2021-01-17 10:15:44",
    		"goodsname": "pytest入门到精",
    		"goodscode": "sp_100011",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 68.8,
    		"stock": 10000,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}, {
    		"id": 111,
    		"create_time": "2021-01-17 10:24:13",
    		"update_time": "2021-01-17 10:24:13",
    		"goodsname": "pytest入门到精",
    		"goodscode": "sp_100012",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 68.8,
    		"stock": 10000,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}]
    }
    

    加密游标分页(CursorPagination)

    游标分页(CursorPagination)的特点是速度快,但不能指定指定查询

    定义CursorPagination查询的一些参数配置

    • cursor_query_param = 'cursor' # 查询的时候,指定的查询方式,默认'cursor'
    • page_size = 3 # 每页显示的条数
    • page_size_query_param = 'size' # 设置size查询参数,默认None
    • max_page_size = 20 # 最多显示条数
    • ordering = 'pk' # 默认排序规则:按pk从小到大排序,-pk表示从大到小排序

    先导入CursorPagination

    # 分页器  -- 加密游标分页
    from rest_framework.pagination import CursorPagination
    
    
    class MyCursorPagination(CursorPagination):
        page_size = 5                   # 默认每页的条数
        page_size_query_param = 'size'  # 查询参数size
        max_page_size = 20              # 最大每页的条数
        ordering = 'pk'   # 默认排序规则:按pk从小到大排序,-pk表示从大到小排序
    
    

    APIView使用加密游标分页

    只能从第一页开始查询,查询的时候结果里面返回了下一页的游标值:cursor=加密串

    from rest_framework import serializers
    from .models import Goods
    from rest_framework.pagination import PageNumberPagination
    from rest_framework.permissions import IsAuthenticated, AllowAny
    # 作者-上海悠悠 QQ交流群:717225969
    # blog地址 https://www.cnblogs.com/yoyoketang/
    
    
    # 序列化 Goods 模型
    class GoodsAPISerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Goods
            fields = '__all__'  # 返回全部的字段
    
    # 分页器  -- 加密游标分页
    class MyCursorPagination(CursorPagination):
        page_size = 5                   # 默认每页的条数
        page_size_query_param = 'size'  # 查询参数size
        max_page_size = 20              # 最大每页的条数
        ordering = 'pk'   # 默认排序规则:按pk从小到大排序,-pk表示从大到小排序
    
    
    
    # 查询视图
    class GoodsAPISView(APIView):
        permission_classes = (AllowAny,)      # AllowAny 允许所有用户
    
    
        def get(self, request, *args, **kwargs):
            '''返回所有的'''
            page = MyCursorPagination()
            goods = Goods.objects.all()   # 查询全部
            ret = page.paginate_queryset(goods, request)
            serializer = GoodsAPISerializer2(ret, many=True)
      
            return Response({
                "code": 0,
                "msg": "success!",
                "next": page.get_next_link(),
                "data": serializer.data
            })
    )
    
    

    查询的时候时候先访问首页http://localhost:8000/api/v1/goods?size=3

    {
    	"code": 0,
    	"msg": "success!",
    	"next": "http://localhost:8000/api/v1/goods?cursor=cD0xNA%3D%3D&size=3",
    	"data": [{
    		"id": 1,
    		"create_time": "2021-01-17 15:14:25",
    		"update_time": "2021-01-19 15:55:17",
    		"goodsname": "《selenium 入门到精通》--修改课程名称",
    		"goodscode": "sp_100049",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 49.0,
    		"stock": -444,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}, {
    		"id": 13,
    		"create_time": "2021-01-16 20:12:36",
    		"update_time": "2021-01-17 09:41:05",
    		"goodsname": "《selenium入门到精通》",
    		"goodscode": "sp_100008",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 49.9,
    		"stock": 100,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}, {
    		"id": 14,
    		"create_time": "2021-01-16 20:12:42",
    		"update_time": "2021-01-17 09:41:05",
    		"goodsname": "《selenium入门到精通》",
    		"goodscode": "sp_100009",
    		"merchantid": "10001",
    		"merchantname": "悠悠学堂",
    		"goodsprice": 49.9,
    		"stock": 100,
    		"goodsgroupid": 0,
    		"goodsstatus": 1
    	}]
    }
    

    从返回的结果里面自动生成下一页的 cursor 游标值(加密串,自动生成的),于是就可以根据next的访问下一页数据

    http://localhost:8000/api/v1/goods?cursor=cD0xNA%3D%3D&size=3

    加密游标分页的优点是安全性高,每次必须拿到cursor=加密串才能访问下一页的数据

  • 相关阅读:
    webpack + vue 向本地后端发送http请求跨域问题
    用FileReader对象从本地读取文件
    oninput与onchange比较
    height: 100% 无效问题
    关于html布局
    圣诞节给自己的犒劳
    django学习之——模版
    django学习之——我的 Hello World
    django学习之——创建项目
    python and pycharm and django 环境配置
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/14298778.html
Copyright © 2020-2023  润新知