Django-DRF-分页

前言

我们数据库有几千万条数据,这些数据需要展示,我们不可能直接从数据库把数据全部读取出来.
因为这样会给内存造成巨大的压力,很容易就会内存溢出,所以我们希望一点一点的取.

同样,展示的时候也是一样的,我们必定会对数据进行分页显示.

本文将详细讲述DRF为我们提供的三种分页方式.

  • 普通分页,看第n页,每页显示m条数据;
  • 切割分页,在n个位置,向后查看m条数据;
  • 加密分页,这与普通分页方式相似,不过对url中的请求页码进行加密。

全局配置

REST_FRAMEWORK = { 
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
        # 对所有分页器生效,但优先级低 
        'PAGE_SIZE': 5, # 每页显示5条数据
}

序列化类

from rest_framework.serializers import ModelSerializerfrom blog.models import Test 
# 导入数据表 
class TestSerializer(ModelSerializer): 
    """用于测试分页的序列化类""" 
    class Meta:  
        model = Test  
        fields = '__all__'

第一种 PageNumberPagination 查第n页,每页显示n条数据

第一步 分页器配置文件

from rest_framework import pagination 
class PageNumberPagination(pagination.PageNumberPagination): 
	"""查第n页,每页显示n条数据""" 
	page_size = 10 # 指定每页显示多少条数据 
	page_size_query_param = 'size' # URL参数中每页显示条数的参数 
	page_query_param = 'page' # URL中页码的参数 
	max_page_size = None # 每页最多显示多少条数据

第二步 视图文件

from rest_framework.response import Responsefrom rest_framework.views 
import APIViewfrom rest_framework.serializers 
import ModelSerializerfrom blog.models 
import Test 
# 导入数据表
from blog import pagination 
# 导入上面的分页配置 
class Test01View(APIView): 
    def get(self, request):  
        queryset = Test.objects.all()   
        # 1. 实例化分页器对象  
        page_obj = pagination.PageNumberPagination()   
        # 2. 使用自己配置的分页器调用分页方法进行分页  
        page_data = page_obj.paginate_queryset(queryset, request)   
        # 3. 序列化我们分页好的数据  
        ser_obj = TestSerializer(page_data, many=True)    
        # 4. 返回数据  
        # return Response(ser_obj.data)   
        # 4. 返回带上一页/下一页连接的页面  
        return page_obj.get_paginated_response(ser_obj.data)

第三步 访问测试

如上图,指定page=10&size=5后,返回了相应的数据.

第二种 LimitOffsetPagination 在第n个位置,向后查n条数据

第一步 分页器配置文件

from rest_framework import pagination 
class LimitOffsetPagination(pagination.LimitOffsetPagination): 
    """在第n个位置,向后查n条数据""" 
    default_limit = 1 # 指定默认查多少条数据 
    limit_query_param = 'limit' # URL中指定查多少条数据的参数 
    offset_query_param = 'offset' # URL中指定从第几条数据开始查的参数 
    max_limit = 999 # 最大显示多少条数据

第二步 视图文件

from rest_framework.response import Responsefrom rest_framework.views 
import APIViewfrom rest_framework.serializers import ModelSerializerfrom blog.models 
import Test # 导入数据表
from blog.pagination import LimitOffsetPagination # 导入上面的分页配置 
class Test02View(APIView): 
    def get(self, request):  
        queryset = Test.objects.all()   
        # 1. 实例化分页器对象  
        page_obj = LimitOffsetPagination()   
        # 2. 使用自己配置的分页器调用分页方法进行分页  
        page_data = page_obj.paginate_queryset(queryset, request)   
        # 3. 序列化我们分页好的数据  
        ser_obj = TestSerializer(page_data, many=True)   
        # # 4. 返回数据  
        # return Response(ser_obj.data)   
        # 4. 返回带上一页/下一页连接的页面  
        return page_obj.get_paginated_response(ser_obj.data)

第三步 访问测试

**第三种 CursorPagination 加密游标的分页

**

第一步 分页器配置文件

from rest_framework import pagination 
class CursorPagination(pagination.CursorPagination): 
    """加密游标的分页""" 
    cursor_query_param = 'cursor'
    page_size = 2  
    ordering = 'id'
    page_size_query_param = 'size' 
    max_page_size = 5  
    
default_limit:#表示默认每页显示几条数据
cursor_query_param:#表示url中页码的参数
page_size_query_param:#表示每页显示数据量的参数
max_page_size:#表示每页最大显示数量,做限制使用,避免突然大量的查询数据,数据库崩溃
ordering:#表示返回数据的排序方式

第二步 视图文件

from rest_framework.response import Responsefrom rest_framework.views import APIViewfrom rest_framework.serializers import ModelSerializerfrom blog.models import Test # 导入数据表from blog.pagination import CursorPagination # 导入上面的分页配置 class Test03View(APIView):     def get(self, request):          queryset = Test.objects.all()           # 1. 实例化分页器对象          page_obj = CursorPagination()           # 2. 使用自己配置的分页器调用分页方法进行分页          page_data = page_obj.paginate_queryset(queryset, request)           # 3. 序列化我们分页好的数据          ser_obj = TestSerializer(page_data, many=True)           # # 4. 返回数据          # return Response(ser_obj.data)           # 4. 返回带上一页/下一页连接的页面          return page_obj.get_paginated_response(ser_obj.data)

好了,打开浏览器去测试吧.

还可以使用DRF视图系统生成带有上一页/下一页按钮的页面.

from rest_framework.viewsets import ModelViewSet class Test04View(ModelViewSet):     queryset = Test.objects.all()     serializer_class = TestSerializer     pagination_class = CursorPagination # 指定分页配置器

如下图:

总结

三种分页中,普通分页与django中的分页基本没有区别。不过要做分页返回给前端数据,就要从数据库中取出数据,然后在做分页序列化。如果用户一下在前几页请求数据库中的最后几页数据,对查询数据库的时延,对数据库的负载较大,就会出现问题,这个时候就可以使用加密分页,限制用户的访问,只提供前一页和后一页的接口。

搜索