Django rest framework 之分页

Posted midworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django rest framework 之分页相关的知识,希望对你有一定的参考价值。

Django rest_framework 中分页可分为三类:

  • PageNumberPagination:看第 n 页,每页显示 n 条数据
  • LimitOffsetPagination:在 n 个位置,向后查看 n 条数据
  • CursorPagination:加密分页,只能看上一页和下一页

一、PageNumberPagination

在这里将采用 rest_framework 内置的页面渲染器 Response

1、api/serializers.py

class PagesSerializers(serializers.ModelSerializer):
    """分页"""

    class Meta:
        model = models.Role
        fields = '__all__'

2、api/views.py

from rest_framework.response import Response    # 渲染器
from .serializers import PagesSerializers

from app import models
from rest_framework.pagination import PageNumberPagination


class PageView(APIView):
    """分页"""
    def get(self, request, *args, **kwargs):
        """示例:
        http://api.example.org/accounts/?page=4
        http://api.example.org/accounts/?page=4&page_size=100
        """
        roles = models.Role.objects.all()
        # 创建分页对象
        pg = PageNumberPagination()
        # 获取分页数据
        page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 将分页后的数据序列化
        roles_ser = PagesSerializers(instance=page_roles, many=True)

        # 将序列化后的数据渲染到前端显示,这里采用的是 rest_framework 的渲染器 Response
        return Response(roles_ser.data)

3、api/urls.py

from django.urls import path, re_path
from api.views import UserView, ParserView, RolesView, UserInfoView, GroupView, UserGroupView, PageView

urlpatterns = [

    re_path('(?P<version>[v1|v2]+)/pages/', PageView.as_view()),    # 分页

]

4、另外需要配置每页显示的条数 settings.py

REST_FRAMEWORK = 
    "DEFAULT_VERSION": 'v1',               # 默认的版本
    "ALLOWED_VERSIONS": ['v1', 'v2'],       # 允许的版本
    "VERSION_PARAM": 'version',             # GET方式url中参数的名字  ?version=xxx
    "PAGE_SIZE": 2,     # 每页最多显示两条数据

5、访问(第二页数据):http://127.0.0.1:8000/api/v2/pages/?page=2

技术图片

自定义分页

定义一个类,让它继承 PageNumberPagination

1、api/views.py

class MyPageNumberPagination(PageNumberPagination):
    """自定义分页类"""
    page_size = 2       # 每页最多显示的条数
    page_query_param = 'page'   # 查询参数,URL 中的过滤参数

    # 通过 page_size 每页只显示 2 条,使用下面这个参数可以改变默认显示条数
    # 使用方法 http://127.0.0.1:8000/api/v2/pages/?page=2&size=3
    page_size_query_param = 'size'
    max_page_size = 10   # 最大页数


class PageView(APIView):
    """分页"""
    def get(self, request, *args, **kwargs):
        """
        http://api.example.org/accounts/?page=4
        http://api.example.org/accounts/?page=4&page_size=100
        """
        roles = models.Role.objects.all()
        # 创建分页对象
        # pg = PageNumberPagination()
        pg = MyPageNumberPagination()
        # 获取分页数据
        page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 将分页后的数据序列化
        roles_ser = PagesSerializers(instance=page_roles, many=True)

        # 将序列化后的数据渲染到前端显示,这里采用的是 rest_framework 的渲染器 Response
        return Response(roles_ser.data)

2、访问:http://127.0.0.1:8000/api/v2/pages/?page=2&size=1

技术图片

二、LimitOffsetPagination

LimitOffsetPagination 可以控制只查看多少条,以及偏移量 offset 后多少条数据,格式为:

http://api.example.org/accounts/?limit=100      # 控制查看 100 条数据
http://api.example.org/accounts/?offset=400&limit=100   # 偏移量 400,查看条数 100,即查看 400 后的 100 条数据

使用方法与 PageNumberPagination 一致:

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

class PageView(APIView):
    """分页"""
    def get(self, request, *args, **kwargs):
        """
        http://api.example.org/accounts/?page=4
        http://api.example.org/accounts/?page=4&page_size=100
        """
        roles = models.Role.objects.all()
        # 创建分页对象
        # pg = PageNumberPagination()
        # pg = MyPageNumberPagination()
        pg = LimitOffsetPagination()
        # 获取分页数据
        page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 将分页后的数据序列化
        roles_ser = PagesSerializers(instance=page_roles, many=True)

        # 将序列化后的数据渲染到前端显示,这里采用的是 rest_framework 的渲染器 Response
        return Response(roles_ser.data)

查看第 2 条数据后的 3 条数据:

技术图片

自定义

同样地 LimitOffsetPagination 也支持自定义:

#自定义分页类2
class MyLimitOffsetPagination(LimitOffsetPagination):
    #默认显示的个数
    default_limit = 2
    #当前的位置
    offset_query_param = "offset"
    #通过limit改变默认显示的个数
    limit_query_param = "limit"
    #一页最多显示的个数
    max_limit = 10

get_paginated_response() 方法控制前后页面

api/views.py

class PageView(APIView):
    """分页"""
    def get(self, request, *args, **kwargs):
        """
        http://api.example.org/accounts/?page=4
        http://api.example.org/accounts/?page=4&page_size=100
        """
        roles = models.Role.objects.all()
        # 创建分页对象
        # pg = PageNumberPagination()
        # pg = MyPageNumberPagination()
        pg = LimitOffsetPagination()
        # 获取分页数据
        page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 将分页后的数据序列化
        roles_ser = PagesSerializers(instance=page_roles, many=True)

        # 将序列化后的数据渲染到前端显示,这里采用的是 rest_framework 的渲染器 Response
        # return Response(roles_ser.data)
        return pg.get_paginated_response(roles_ser.data)        # 这一行

效果如下:

技术图片

三、CursorPagination

CursorPagination 将页码进行加密,使得不能通过 URL 来控制显示的页面

1、这里使用自定义分页类 api/views.py

class MyCursorPagination(CursorPagination):
    """自定义分页类"""
    page_size = 2       # 每页最多显示的条数
    cursor_query_param = 'cursor'   # 查询参数,URL 中的过滤参数

    ordering = 'id'       # 通过什么排序(正序)
    page_size_query_param = None
    max_page_size = None  # 最大页数


class PageView(APIView):
    """分页"""
    def get(self, request, *args, **kwargs):
        """
        http://api.example.org/accounts/?page=4
        http://api.example.org/accounts/?page=4&page_size=100
        """
        roles = models.Role.objects.all()
        # 创建分页对象
        # pg = PageNumberPagination()
        # pg = MyPageNumberPagination()
        # pg = LimitOffsetPagination()
        pg = MyCursorPagination()
        # 获取分页数据
        page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
        # 将分页后的数据序列化
        roles_ser = PagesSerializers(instance=page_roles, many=True)

        # 将序列化后的数据渲染到前端显示,这里采用的是 rest_framework 的渲染器 Response
        # return Response(roles_ser.data)
        return pg.get_paginated_response(roles_ser.data)

2、访问: http://127.0.0.1:8000/api/v2/pages/

技术图片

以上是关于Django rest framework 之分页的主要内容,如果未能解决你的问题,请参考以下文章

REST framwork之分页器,路由器,响应器

Django-rest-framework多条件查询/分页/多表Json

关闭 Django Rest Framework ModelViewSet 的自动分页

Django Rest Framework:在 ViewSet 上打开分页(如 ModelViewSet 分页)

Django Rest Framework 分页极慢计数

drf之分页器