• drf(八)—分页


    drf(八)—分页

    说明:分页的原理与数据库中的 limit 截取相关,也涉及limit offset的使用,内部原理相似,但是rest_framework中封装了应用函数。

    分页基类

    class BasePagination:
        display_page_controls = False
    
        def paginate_queryset(self, queryset, request, view=None):  # pragma: no cover
            raise NotImplementedError('paginate_queryset() must be implemented.')
    
        def get_paginated_response(self, data):  # pragma: no cover
            raise NotImplementedError('get_paginated_response() must be implemented.') # 自动生成页码,并将对象进行序列化的操作。
    
        def get_paginated_response_schema(self, schema):
            return schema
    
        def to_html(self):  # pragma: no cover
            raise NotImplementedError('to_html() must be implemented to display page controls.')
    
        def get_results(self, data):
            return data['results']
    
        def get_schema_fields(self, view):
            assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
            return []
    
        def get_schema_operation_parameters(self, view):
            return []
    

    1.普通的参数分页

    class MyPageNumberPagination(PageNumberPagination):
        page_size = 2 # 每页显示多少条数据
        page_query_param = 'page'
        page_size_query_param = 'size' # 路由中增加参数
    
        max_page_size = 5 # 
    
    
    class Pager1View(APIView):
    
        def get(self,request,*args,**kwargs):
            roles=models.Role.objects.all()
    
            # 创建分页对象
            pg=MyPageNumberPagination()
            # 在数据库中获取分页数据
            pager_roles=pg.paginate_queryset(queryset=roles,request=request,view=self)
            # 对数据进行序列化,将分页数据进行序列化
            ser=RoleSerializers(instance=pager_roles,many=True)
            # 使用渲染器进行放回
            return Response(ser.data)
    

    image-20220410183156310

    image-20220410183407242

    image-20220410183427399

    内部源码

    class PageNumberPagination(BasePagination):
        page_size = api_settings.PAGE_SIZE # 可以去配置文件中读取,但是一般只是在子类中配置
    
        django_paginator_class = DjangoPaginator
    
        # Client can control the page using this query parameter.
        page_query_param = 'page'
        page_query_description = _('A page number within the paginated result set.')
    
        # Client can control the page size using this query parameter.
        # Default is 'None'. Set to eg 'page_size' to enable usage.
        page_size_query_param = None
        page_size_query_description = _('Number of results to return per page.')
    
        # Set to an integer to limit the maximum page size the client may request.
        # Only relevant if 'page_size_query_param' has also been set.
        max_page_size = None
    
        last_page_strings = ('last',)
    
        template = 'rest_framework/pagination/numbers.html'
    
        invalid_page_message = _('Invalid page.')
    
        def paginate_queryset(self, queryset, request, view=None):
            page_size = self.get_page_size(request)
            if not page_size:
                return None
    
            paginator = self.django_paginator_class(queryset, page_size)
            page_number = self.get_page_number(request, paginator)
    
            try:
                self.page = paginator.page(page_number)
            except InvalidPage as exc:
                msg = self.invalid_page_message.format(
                    page_number=page_number, message=str(exc)
                )
                raise NotFound(msg)
    
            if paginator.num_pages > 1 and self.template is not None:
                # The browsable API should display pagination controls.
                self.display_page_controls = True
    
            self.request = request
            return list(self.page)
    
    

    自定义的字段主要使用在上述使用的参数。

    2. limit 分页

    class MyLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 2
        limit_query_param = 'limit'
        offset_query_param = 'offset'
        max_limit = 4
    

    image-20220410184835235

    源码:

    class LimitOffsetPagination(BasePagination):
        default_limit = api_settings.PAGE_SIZE
        limit_query_param = 'limit'
        limit_query_description = _('Number of results to return per page.')
        offset_query_param = 'offset'
        max_limit = None
    

    超出索引范围。只显示最大的条数。

    image-20220410184711580

    传入 offset 参数,从 offset 位置后取出 limit 条数据;

    image-20220410190758056

    调用生成url的方法也可以生成下一页的url连接。

    3.生成安全页码的分页

    说明:生成页码的功能其他类也有,只是安全页码的功能,页码参数是加密字符串。

    class MyCursorPagination(CursorPagination):
        cursor_query_param = 'cursor'
        page_size = 2
        ordering = 'id' # 排序规则,'-id'则会修改为倒叙
        page_size_query_param = None
        max_page_size = None
    

    视图函数:

    class Pager1View(APIView):
    
        def get(self,request,*args,**kwargs):
            roles=models.Role.objects.all()
    
            # 创建分页对象
            # pg=MyPageNumberPagination()
    
            # pg=MyLimitOffsetPagination()
    
            pg=MyCursorPagination()
    
            # 在数据库中获取分页数据
            pager_roles=pg.paginate_queryset(queryset=roles,request=request,view=self)
            # 对数据进行序列化,将分页数据进行序列化
            ser=RoleSerializers(instance=pager_roles,many=True)
            # 使用渲染器进行放回
            # return Response(ser.data)
            
            # 使用方语句生成页码
            return pg.get_paginated_response(ser.data)
    

    image-20220410190359356

    页码参数cursor也是加密字符。

    原理与数据库分页相关,数量巨大的时候与数据库的性能也相关;

    继续努力,终成大器;

  • 相关阅读:
    魔兽70TBC猎人常用宏
    魔兽70TBC猎人宝宝技能汇总
    redis常用概念
    mongodb分片集群开启安全认证
    mongodb集群搭建(分片+副本)
    mongodb 用户权限控制
    greenplum数据迁移
    greenplum资源队列
    GreenPlum 集群常用命令
    COCOS 实现Player玩家控制的左右控制,实现马里奥一样的移动
  • 原文地址:https://www.cnblogs.com/Blogwj123/p/16127107.html
Copyright © 2020-2023  润新知