Pagination

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

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

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

PageNumberPagination

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

DRF的分页组件PageNumberPagination源码

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

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

pagination:

url:

view:

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

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

相关代码:

pagination

  1. from rest_framework.pagination import PageNumberPagination
  2.  
  3. class MyPagination(PageNumberPagination):
  4. page_size = 2
  5. page_size_query_param = 'size'
  6. max_page_size = 3

url:

  1. from django.urls import path, re_path, include
  2. from demo1.views import BookView
  3.  
  4. urlpatterns = [
  5. path('book', BookView.as_view()),
  6. ]

view:

  1. from demo1.serializers import BookSerializer
  2. from rest_framework.views import APIView
  3. from demo1.models import Book
  4. from utils.pagination import MyPagination
  5.  
  6. class BookView(APIView):
  7.  
  8. def get(self, request):
  9. queryset = Book.objects.all()
  10. # 1,实例化分页器对象
  11. page_obj = MyPagination()
  12. # 2,调用分页方法去分页queryset
  13. page_queryset = page_obj.paginate_queryset(queryset, request, view=self)
  14. # 3,把分页好的数据序列化
  15. ser_obj = BookSerializer(page_queryset, many=True)
  16. # 4, 带着上一页下一页连接的响应
  17. return page_obj.get_paginated_response(ser_obj.data)

serializer:

  1. class BookSerializer(serializers.ModelSerializer):
  2. category_display = serializers.SerializerMethodField(read_only=True)
  3. authors = serializers.SerializerMethodField(read_only=True)
  4. publish_info = serializers.SerializerMethodField(read_only=True)
  5.  
  6. def get_category_display(self, obj):
  7. return obj.get_category_display()
  8.  
  9. def get_publish_info(self, obj):
  10. publish_obj = obj.publisher
  11. return {"id": publish_obj.id, 'title': publish_obj.title}
  12.  
  13. def get_authors(self, obj):
  14. # obj是Book对象
  15. author_list = obj.author.all()
  16. return [{"id": author_obj.id, "name": author_obj.name} for author_obj in author_list]
  17.  
  18. class Meta:
  19. model = models.Book
  20. fields = '__all__'
  21. # depth = 1 # 表示外键查找层级
  22. extra_kwargs = {
  23. "category": {"write_only": True}, "publisher": {"write_only": True},
  24. "author": {"write_only": True},
  25. }

LimitOffsetPagination

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

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

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

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

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

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

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

相关代码:

pagination:

  1. from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
  2.  
  3. class MyPagination(LimitOffsetPagination):
  4. default_limit = 1
  5. max_limit = 3

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

  1. from demo1.serializers import BookSerializer
  2. from rest_framework.views import APIView
  3. from demo1.models import Book
  4. from utils.pagination import MyPagination
  5.  
  6. class BookView(APIView):
  7.  
  8. def get(self, request):
  9. queryset = Book.objects.all()
  10. # 1,实例化分页器对象
  11. page_obj = MyPagination()
  12. # 2,调用分页方法去分页queryset
  13. page_queryset = page_obj.paginate_queryset(queryset, request, view=self)
  14. # 3,把分页好的数据序列化
  15. ser_obj = BookSerializer(page_queryset, many=True)
  16. # 4, 带着上一页下一页连接的响应
  17. return page_obj.get_paginated_response(ser_obj.data)

View

  1. from django.urls import path, re_path, include
  2. from demo1.views import BookView
  3.  
  4. urlpatterns = [
  5. path('book', BookView.as_view()),
  6. ]

url

  1. from rest_framework import serializers
  2. from demo1 import models
  3.  
  4. class PublishSerializer(serializers.Serializer):
  5. id = serializers.IntegerField()
  6. title = serializers.CharField(max_length=32)
  7.  
  8. class AuthorSerializer(serializers.Serializer):
  9. id = serializers.IntegerField()
  10. name = serializers.CharField(max_length=32)
  11.  
  12. class BookSerializer(serializers.ModelSerializer):
  13. category_display = serializers.SerializerMethodField(read_only=True)
  14. authors = serializers.SerializerMethodField(read_only=True)
  15. publish_info = serializers.SerializerMethodField(read_only=True)
  16.  
  17. def get_category_display(self, obj):
  18. return obj.get_category_display()
  19.  
  20. def get_publish_info(self, obj):
  21. publish_obj = obj.publisher
  22. return {"id": publish_obj.id, 'title': publish_obj.title}
  23.  
  24. def get_authors(self, obj):
  25. # obj是Book对象
  26. author_list = obj.author.all()
  27. return [{"id": author_obj.id, "name": author_obj.name} for author_obj in author_list]
  28.  
  29. class Meta:
  30. model = models.Book
  31. fields = '__all__'
  32. # depth = 1 # 表示外键查找层级
  33. extra_kwargs = {
  34. "category": {"write_only": True}, "publisher": {"write_only": True},
  35. "author": {"write_only": True},
  36. }

serializers

CursorPagination

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

pagination:

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

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

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

相关代码:

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

pagination

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

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

  1. # coding:utf-8
  2. from rest_framework.generics import GenericAPIView
  3. from rest_framework.mixins import ListModelMixin
  4. from demo1.serializers import BookSerializer
  5. from demo1.models import Book
  6. from utils.pagination import MyPagination
  7.  
  8. class BookView(GenericAPIView,ListModelMixin):
  9. queryset = Book.objects.all()
  10. serializer_class = BookSerializer
  11. pagination_class = MyPagination
  12.  
  13. def get(self, request):
  14. return self.list(request)

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

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

总结:

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

前后端分离djangorestframework——分页组件的更多相关文章

  1. 前后端分离djangorestframework——路由组件

    在文章前后端分离djangorestframework——视图组件 中,见识了DRF的视图组件强大,其实里面那个url也是可以自动生成的,就是这么屌 DefaultRouter urls文件作如下调整 ...

  2. 前后端分离djangorestframework——视图组件

    CBV与FBV CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用reque ...

  3. 前后端分离djangorestframework——认证组件

    authentication 认证是干嘛的已经不需要多说.而前后端未分离的认证基本是用cookie或者session,前后端分离的一般用token 全局认证 先创建一个django项目,项目名为drf ...

  4. 前后端分离djangorestframework——ContentType组件表

    ContentType ContentType其实django自带的,但是平时的话很少会用到,所以还是放在Djangorestframework这个部分 作用: 在实际的开发中,由于数据库量级大,所以 ...

  5. 前后端分离djangorestframework——权限组件

    权限permissions 权限验证必须要在认证之后验证 权限组件也不用多说,读了源码你就很清楚了,跟认证组件很类似 具体的源码就不展示,自己去读吧,都在这里: 局部权限 设置model表,其中的ty ...

  6. 前后端分离djangorestframework—— 在线视频平台接入第三方加密防盗录视频

    加密视频 在以后的开发项目中,很可能有做在线视频的,而在线视频就有个问题,因为在线播放,就很有可能视频数据被抓包,如果这个在线视频平台有付费视频的话,这样就会有人做点倒卖视频的生意了,针对这个问题,目 ...

  7. 前后端分离djangorestframework—— 接入第三方的验证码平台

    关于验证码部分,在我这篇文章里说的挺详细的了:Python高级应用(3)—— 为你的项目添加验证码 这里还是再给一个前后端分离的实例,因为极验官网给的是用session作为验证的,而我们做前后端分离的 ...

  8. 前后端分离djangorestframework——序列化与反序列化数据

    我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就 ...

  9. 前后端分离djangorestframework——restful规范

    restful现在非常流行,所以很有必要提一下 web服务交互 在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候,都需要前后端交互,前后端交互就一定有一些实现方案,我 ...

随机推荐

  1. spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!

    前言 项目框架主要是spring,持久层框架没有用mybtis,用的是spring 的jdbc: 业务需求:给应用添加领域(一个领域包含多个应用,一个应用可能属于多个领域,一般而言一个应用只属于一个领 ...

  2. Mycat - 高可用与负载均衡实现,满满的干货!

    前言 开心一刻 和朋友去吃小龙虾,隔壁桌一个小女孩问妈妈:"妈妈,小龙虾回不了家,它妈妈会不会着急?" 她妈妈愣住了,我扒虾的手停下了,这么善良的问题,怎么下得了口.这是老板急忙过 ...

  3. Android Navigation 架构组件入门教程

    Android Navigation 架构组件入门教程 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:https://www.cnblogs.com/cavalier-/p/1 ...

  4. Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  5. vue_drf之多级过滤、排序、分页

    一.前端代码 1,父组件free_course.vue <template> <div id="free_course"> <el-container ...

  6. 业务开发(六)—— MyBatis框架

    0x01.元素内容必须由格式正确的字符数据或标记组成. Caused by: org.apache.ibatis.builder.BuilderException: Error creating do ...

  7. Python爬虫之自制英汉字典

      最近在微信公众号中看到有人用Python做了一个爬虫,可以将输入的英语单词翻译成中文,或者把中文词语翻译成英语单词.笔者看到了,觉得还蛮有意思的,因此,决定自己也写一个玩玩~~   首先我们的爬虫 ...

  8. ife2018 零基础学院 day 4

    第四天,背景边框列表链接和更复杂的选择器 背景,边框,列表,链接相关属性 背景 MDN 背景 W3School 背景 元素的背景是指,在元素内容.内边距和边界下层的区域. 属性 描述 backgrou ...

  9. 操作失败: 无法更改关系,因为一个或多个外键属性不可以为 null

    报错:操作失败: 无法更改关系,因为一个或多个外键属性不可以为 null  . 同时修改主表和从表的数据,想用EF主表T_ReviewPlan中某个对象item删除item对应的从表T_ReviewS ...

  10. 回客科技 面试的 实现ioc 容器用到的技术,简述BeanFactory的实现原理,大搜车面试的 spring 怎么实现的依赖注入(DI)

    前言:这几天的面试,感觉自己对spring 的整个掌握还是很薄弱.所以需要继续加强. 这里说明一下spring的这几个面试题,但是实际的感觉还是不对的,这种问题我认为需要真正读了spring的源码后说 ...