• DRF分页器(Django Restful Framework)


    资料推荐

    官方文档
    https://q1mi.github.io/Django-REST-framework-documentation/api-guide/pagination_zh/
    B站没有好的教学视频,不建议看,直接看官方文档吧。

    PageNumberPagination

    此分页样式接受请求查询参数中的单个数字页码。
    Request:

    GET https://api.example.org/accounts/?page=4
    

    Response:

    {
        "count": 1023
        "next": "https://api.example.org/accounts/?page=5",
        "previous": "https://api.example.org/accounts/?page=3",
        "results": [
           …
        ]
    }
    

    Settings:

    全局设置

    全局启用 PageNumberPagination 样式,请使用以下配置,并根据需要设置 PAGE_SIZE

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 100
    }
    

    单视图设置(重点!)

    自定义继承子类

    自定义一个继承自PageNumberPagination的分页器,然后在里面设置page_size,如下:

    class LargeResultsSetPagination(PageNumberPagination):
        page_size = 1000
        page_size_query_param = 'page_size' # 非必需
        max_page_size = 10000 # 非必需
    

    重写get_paginate_by方法

    如果只想用PageNumberPagination本身,那么需要通过重写get_paginate_by方法来设置page_size。

    class YourView(generics.ListAPIView):
        queryset = YourModel.objects.all()
        serializer_class = YourSerializer
    
        # 使用官方的 PageNumberPagination 类
        pagination_class = PageNumberPagination
    
        # 覆盖默认的分页设置
        def get_paginate_by(self, queryset):
            return self.request.query_params.get('page_size', 5)
    

    LimitOffsetPagination

    这种分页样式反映了查找多个数据库记录时使用的语法。客户端包括“limit”和“offset”查询参数。limit指示要返回的项目的最大数目,这相当于其他样式中的 page_size。offset指示查询相对于完整的未分页项的起始位置。
    Request:

    GET https://api.example.org/accounts/?limit=100&offset=400
    

    Response:

    HTTP 200 OK
    {
        "count": 1023
        "next": "https://api.example.org/accounts/?limit=100&offset=500",
        "previous": "https://api.example.org/accounts/?limit=100&offset=300",
        "results": [
           …
        ]
    }
    

    Settings:

    全局设置

    为了全局启用 LimitOffsetPagination样式,请使用以下配置:

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    	'PAGE_SIZE': 10
    }
    

    ps:又是一个易错点,虽然limitoffsetpagination用的是limit,但是全局设置时还是要设置PAGE_SIZE。。

    单视图设置(重点!)

    自定义继承子类实现

    自定义一个继承自LimitOffsetPagination的分页器,然后在里面设置limit,如下:

    class CustomLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 5  # 自定义默认每页显示的数量,一定要给
        max_limit = 20  # 自定义每页显示的最大数量,非必需
    

    重写get_paginate_by

    如果只想用LimitOffsetPagination本身,那么需要通过重写get_paginate_by方法来设置limit。

    from rest_framework import generics
    from rest_framework.pagination import LimitOffsetPagination
    
    class YourView(generics.ListAPIView):
        queryset = YourModel.objects.all()
        serializer_class = YourSerializer
        pagination_class = LimitOffsetPagination  # 使用 LimitOffsetPagination
    
        # 覆盖默认的分页设置
        def get_paginate_by(self, queryset):
            return self.request.query_params.get('limit', 10)
    

    获取分页输出样式/具体如何使用分页器(重点!)

    像是如上的

    {
        "count": 1023
        "next": "https://api.example.org/accounts/?page=5",
        "previous": "https://api.example.org/accounts/?page=3",
        "results": [
           …
        ]
    }
    
    {
        "count": 1023
        "next": "https://api.example.org/accounts/?limit=100&offset=500",
        "previous": "https://api.example.org/accounts/?limit=100&offset=300",
        "results": [
           …
        ]
    }
    

    都是pagenumberpagination、limitoffsetpagination等官方分页器通过get_paginated_response返回的默认的分页样式。

    具体使用如下:

    class CustomLimitOffsetPagination(LimitOffsetPagination):
        default_limit = 5  # 自定义默认每页显示的数量
    
    class YourView(generics.ListAPIView):
        queryset = YourModel.objects.all()
        serializer_class = YourSerializer
        pagination_class = CustomLimitOffsetPagination  # 使用自定义分页类
    
        def get(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)  # 对查询集进行分页
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)  # 获取分页样式的响应
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    

    自定义分页输出样式(重写get_paginated_response方法!!重要!)

    假设我们想用一个修改过的格式替换默认的分页输出样式,该格式在嵌套的“links”键中包含下一页和上一页的链接。我们就需要自定义分页器,并重写get_paginated_response方法

    class CustomPagination(pagination.PageNumberPagination):
        def get_paginated_response(self, data):
            return Response({
                'links': {
                   'next': self.get_next_link(),
                   'previous': self.get_previous_link()
                },
                'count': self.page.paginator.count,
                'results': data
            })
    

    最常使用场景举例

    from rest_framework.pagination import LimitOffsetPagination
    
    from utils import ThirdPartResponse
    
    
    class TaskPagination(LimitOffsetPagination):
        default_limit = 5  # 自定义默认每页显示的数量,一定要给。及时后续会在请求参数中拿到limit,也一定要给
    
        def get_paginated_response(self, data):
            return ThirdPartResponse(data={"total": self.count, "data": data})
    
    @action(detail=False, methods=["get"], url_path="list-by-template/(?P.+)")
    def list_by_template(self, request, template_id=None):
        """
        根据template_id过滤任务列表
        """
        if template_id is None:
            message = "template_id is required"
            logger.error(message)
            return ThirdPartResponse(result=False, message=message)
        tasks = self.queryset.filter(template_id=template_id)
    
        paginator = TaskPagination()
        page = paginator.paginate_queryset(tasks, request)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return paginator.get_paginated_response(serializer.data)
        serializer = self.get_serializer(tasks, many=True)
        return Response(serializer.data)
    
  • 相关阅读:
    计网第五章(运输层)(六)(TCP可靠传输的实现)
    开源日志库log4cpp & muduo
    51nod 22.7暑假冲刺联训CSP-J 第一场II D题
    基于Spring Boot+Vue的宠物服务管理系统-计算机毕业设计
    数据结构与算法【二叉搜索树】Java实现
    从0手写两轮差速机器人urdf模型
    数据结构c语言版第二版(严蔚敏)第四章笔记
    学GoWorld,go 1.21
    C#基础笔记
    四川竹哲电子商务有限公司创造抖音电商新高度
  • 原文地址:https://blog.csdn.net/zhiaidaidai/article/details/139639280