REST_FRAMEWORK重要组件--->Pagination
6.分页(Pagination)
(1).其实分页的作用很大一部分是将数据按照特定的需要,有序的排列出来。像从数据库中提取出来的数据类型为queryset,可以经过serializers(序列化器)的转化变成json,在通过rest_framework的response.Response类(渲染返回)进行一个比较好看的数据显示(Response返回的结果类型还是Dict)。如果需要全部数据的依次显示,或者部分数据的摘取显示,则Pagination(分页器)就比较重要了。
(2).分页器可以按照要求分成三类分页器:
A.你想要看第N页,每页显示N条数据内容(PageNumberPagination)
B.在第N条数据的位置,向后查看N条数据,有点类似于seek(LimitOffsetPagination)
C.加密分页 显示上一页和下一页的url地址链接,关键字段page和page_size被加密,无法进行
带参找到相对应的数据。(CursorPagination)
(3).为何需要分页器?那如何解决这一问题提高查看效率?
答:当数据库性能优秀和数据量规模较小的时候,这个问题忽略。但是如果不是的话,就要考虑数据遍历和数据结果响应时间问题。我们假设一页的数据量为10条,offset的下标为0开始,那么第一页的数据就是遍历0-9,结束。第二页,遍历0-19取10-19,结束。第三页,遍历0-29,取20-29,结束。那我们假设如果我们点击了很多页,或者每页的信息条数为20条是,遍历数据表的速度就会变慢,相应的时间就会增加。解决的方案有两种:1.我们知道每一页的数据都有一个最大和最小id,下一页可以记住上一页的最大最小id进行一个判断查找。2.我们做一个限制查找,比如我们假设一个人人的最大查看量就是10页,那我们就做一个20页的一次性遍历。他最多就是查看20页的内容,无法继续查看下去。
(4).因为Pagination可以有关键字带参数查找数据,比如page_size_query_param/page_query_param等其实是可以在url上写上?page_size=3&page=1这样形式的参数的,表示为显示第一页,每页显示三条数据。那万一有些人就是存心调戏服务器写了一个?page_size=10000&page=1,这样就爆了。不同Pagination类都是设置有最大值字段的**。PageNumberPagination为max_query_param
/LimitOffsetPagination为max_limit/CursorPagination为max_page_size
(5).A、B、C方式的实现
A的实现方法(你想要看第N页,每页显示N条数据内容):
from rest_framework.views import APIView
from . import models
from rest_framework.pagination import PageNumberPagination
class MyPagenumberPagination(PageNumberPagination):
page_size = 2 #每页2条数据的现实
page_size_query_param = 'page_size' #作为url传参多少条的关键字
page_query_param = 'page' #作为url传参第几页的关键字
max_page_size = 10 #每页显示数据的最大条数
from rest_framework import serializers
class pageSerianlizer(serializers.ModelSerializer):
class Meta: #利用ModelSerializer快速做一个全字段的序列化器
model=models.Userinfo
fields='__all__'
class pager1(APIView):
authentication_classes = [ ]
permission_classes = [ ] #之前在全局做了一下认证、权限、节流,三行可以忽略
throttle_classes = [ ]
def get(self,request,*args,**kwargs):
from . import models
from rest_framework.response import Response
users=models.Userinfo.objects.all()
print(users)
pg=MyPagenumberPagination() #我是继承PageNumberPagination
# 然后更改了继承下来的那些变量值
#page_size = 2
#page_size_query_param = 'page_size'
#page_query_param = 'page'
# max_page_size = 10
pager=pg.paginate_queryset(queryset=users,request=request,view=self)
#将queryset的对象传给实例化pg的paginate_queryset()方法
#queryset就是模型的对象,request=request,view是视图对象,self为当前视图
ser=pageSerianlizer(instance=pager,many=True)
#序列化
return Response(ser.data)
#利用rest_framework的response.Respose进行渲染返回。
B的实现方法(在第N条数据的位置,向后查看N条数据):
from rest_framework.pagination import LimitOffsetPagination
class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit' #查看几条数据,下面已经定死了,不可能超过10条,上面默认为两条
offset_query_param = 'offset' #光标的其实位置
max_limit = 10
在自定义的pager1视图中改一句:pg=MyLimitOffsetPagination()
C的实现方法(加密分页 显示上一页和下一页的url地址链接):
from rest_framework.pagination import CursorPagination
class MyCursorPagination(CursorPagination):
max_page_size = 5
cursor_query_param = 'cursor'
page_size_query_param = 'page_size'
page_size = 2
ordering = '-username' #排序
在自定义的pager1视图中改一句:pg=MyCursorPagination()
利用C的实现方法可以用return pg.get_paginated_response(ser.data) 方法返回,这样可以显示上下页面的链接