博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前后端分离djangorestframework——分页组件
阅读量:5949 次
发布时间:2019-06-19

本文共 6020 字,大约阅读时间需要 20 分钟。

 

Pagination

为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件

 

这次用    文章里用到的数据,数据库用的mysql,因为django自带的sqlite对于日期类型的数据会自动转成时间戳,导致数据再序列化时无法正常序列化成日期类型而出错

 

分页组件还是跟前面的认证组件,权限组件,频率组件很类似的

 

PageNumberPagination

在根目录创建一个utils文件夹,在该文件夹里创建一个pagination文件,在其内定义一个分页组件类,继承自DRF里自带的PageNumberPagination类:

DRF的分页组件PageNumberPagination源码

 

且注意这两个方法,paginate_queryset和get_paginated_response,后面视图类里会用到

 

 

 

 

读django的源码,可知我们可以自定义一些属性或方法:

pagination:

url:

 

 view:

 

 

访问测试,显示一共8个数据,有上一页下一页,当前显示两个数据,这是刚才自定义分页组件时定义的

 

并且这个上一页下一页是可以直接点击的

 

相关代码:

pagination

from rest_framework.pagination import PageNumberPaginationclass MyPagination(PageNumberPagination):    page_size = 2    page_size_query_param = 'size'    max_page_size = 3

url:

from django.urls import path, re_path, includefrom demo1.views import BookViewurlpatterns = [    path('book', BookView.as_view()),]

 

view:

from demo1.serializers import BookSerializerfrom rest_framework.views import APIViewfrom demo1.models import Bookfrom utils.pagination import MyPaginationclass BookView(APIView):    def get(self, request):        queryset = Book.objects.all()        # 1,实例化分页器对象        page_obj = MyPagination()        # 2,调用分页方法去分页queryset        page_queryset = page_obj.paginate_queryset(queryset, request, view=self)        # 3,把分页好的数据序列化        ser_obj = BookSerializer(page_queryset, many=True)        # 4, 带着上一页下一页连接的响应        return page_obj.get_paginated_response(ser_obj.data)

 

serializer:

class BookSerializer(serializers.ModelSerializer):    category_display = serializers.SerializerMethodField(read_only=True)    authors = serializers.SerializerMethodField(read_only=True)    publish_info = serializers.SerializerMethodField(read_only=True)    def get_category_display(self, obj):        return obj.get_category_display()    def get_publish_info(self, obj):        publish_obj = obj.publisher        return {
"id": publish_obj.id, 'title': publish_obj.title} def get_authors(self, obj): # obj是Book对象 author_list = obj.author.all() return [{
"id": author_obj.id, "name": author_obj.name} for author_obj in author_list] class Meta: model = models.Book fields = '__all__' # depth = 1 # 表示外键查找层级 extra_kwargs = { "category": {
"write_only": True}, "publisher": {
"write_only": True}, "author": {
"write_only": True}, }

 

LimitOffsetPagination

同样的自定义分页组件,并继承此类即可:

pagination,其中的两个属性是看LimitOffsetPagination的源码所得:

 

其他不用改,重启项目访问测试,一页只有一个数据,有上一页下一页的链接

并且上一页和下一页可以直接点击:

 

看起来好像和前面的PageNumberPagination差距不大对吧?LimitOffsetPagination,其参数offset是从第几个开始向后找,limit是只一次显示多少条数据的

当然你可以手动修改url的条件参数,从第一个开始找,每次显示8,这样就把我们本来就只有8个数据一起显示了

说到这,顺便说下,之前我们研究的Python爬虫, 有时候在爬数据时是发现网页没有刷新,但是是ajax异步请求,每次请求只显示一定数量的,就是因为有这个limit参数在,当时我们是怎么解决呢?就是直接在url后面修改limit参数,一次请求几百条数据或者多少都行,这样我们只请求了一次,但是这一下就拿到了多条数据,前面我们用的频率组件可以限制次数,到这我们一次请求拿几百或者几千这种的,就不好判断了

 

相关代码:

pagination:

from rest_framework.pagination import PageNumberPagination,LimitOffsetPaginationclass MyPagination(LimitOffsetPagination):    default_limit = 1    max_limit = 3

view和url,serializers其实都没做任何更改:

from demo1.serializers import BookSerializerfrom rest_framework.views import APIViewfrom demo1.models import Bookfrom utils.pagination import MyPaginationclass BookView(APIView):    def get(self, request):        queryset = Book.objects.all()        # 1,实例化分页器对象        page_obj = MyPagination()        # 2,调用分页方法去分页queryset        page_queryset = page_obj.paginate_queryset(queryset, request, view=self)        # 3,把分页好的数据序列化        ser_obj = BookSerializer(page_queryset, many=True)        # 4, 带着上一页下一页连接的响应        return page_obj.get_paginated_response(ser_obj.data)
View
from django.urls import path, re_path, includefrom demo1.views import BookViewurlpatterns = [    path('book', BookView.as_view()),]
url
from rest_framework import serializersfrom demo1 import modelsclass PublishSerializer(serializers.Serializer):    id = serializers.IntegerField()    title = serializers.CharField(max_length=32)class AuthorSerializer(serializers.Serializer):    id = serializers.IntegerField()    name = serializers.CharField(max_length=32)class BookSerializer(serializers.ModelSerializer):    category_display = serializers.SerializerMethodField(read_only=True)    authors = serializers.SerializerMethodField(read_only=True)    publish_info = serializers.SerializerMethodField(read_only=True)    def get_category_display(self, obj):        return obj.get_category_display()    def get_publish_info(self, obj):        publish_obj = obj.publisher        return {
"id": publish_obj.id, 'title': publish_obj.title} def get_authors(self, obj): # obj是Book对象 author_list = obj.author.all() return [{
"id": author_obj.id, "name": author_obj.name} for author_obj in author_list] class Meta: model = models.Book fields = '__all__' # depth = 1 # 表示外键查找层级 extra_kwargs = { "category": {
"write_only": True}, "publisher": {
"write_only": True}, "author": {
"write_only": True}, }
serializers

 

CursorPagination

这个游标分页,可以对访问的url的条件参数隐藏,防止被人根据url的条件参数猜出我们的数据量,可能有潜在的隐患

 

pagination:

 

访问测试,按id为11(11为数据库里的最后一个数据)开始倒序排序

 打开数据库,确实是倒序的

 

再点击上一页下一页,发现其参数是加密了的,根本无法通过这个条件参数猜解出我们的数据量

 

 

 

 相关代码:

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPaginationclass MyPagination(CursorPagination):    page_size = 2    ordering = '-id'  # 表示从哪个字段开始排序
pagination

其他没有做任何更改,不再贴出浪费篇幅了

 

当然,这个还是可以使用之前的Modelserializer来优化代码,

 

# coding:utf-8from rest_framework.generics import GenericAPIViewfrom rest_framework.mixins import ListModelMixinfrom demo1.serializers import BookSerializerfrom demo1.models import Bookfrom utils.pagination import MyPaginationclass BookView(GenericAPIView,ListModelMixin):    queryset = Book.objects.all()    serializer_class = BookSerializer    pagination_class = MyPagination    def get(self, request):        return self.list(request)

 

其他不用作任何更改,访问测试:

 

为什么这么方便,因为ListModelMixin中做了处理,假如有分页组件,那么就获取了分页的参数再返回:

 

 

总结:

 多看源码,根据需求选用源码的分页组件类,设定相关的参数

 

转载于:https://www.cnblogs.com/yangva/p/10428496.html

你可能感兴趣的文章
JAVAEE-junit测试hibernate里的方法(hibernate交给spring管理)的问题
查看>>
MOTO MB860 国行2.3.5优化增强ROM_Top_T5_end(经典收藏版)
查看>>
C#学习经典(二)---MVC框架(Model view Controller)
查看>>
我的友情链接
查看>>
log4j配置文件说明
查看>>
Maven: 为Compiler插件设置source和target版本
查看>>
L2TP/IPSec一键安装脚本
查看>>
linux下永久添加静态路由
查看>>
android 全局变量和局部变量命名规则
查看>>
Ubuntu Sub-process /usr/bin/dpkg
查看>>
详解DNS的常用记录(下):DNS系列之三
查看>>
“爆炸门”苹果补刀,三星该“哭晕了”!
查看>>
基于linux的3款压力测试工具:Siege,webbench,ab
查看>>
Netty Buffer
查看>>
icinga2使用check_snmp_idrac.py监控DELL硬件状态
查看>>
Java基础学习21(代码块)
查看>>
陈松松:无需懂任何视频制作技术,就能做出让客户感觉专业的视频
查看>>
转:用Windows Live Writer在51CTO写博客
查看>>
rsync+ssh的无验证登录
查看>>
我的友情链接
查看>>