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<template_id>.+)")
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)
  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸡鸭扣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值