前言:

  分页大家应该都很清楚,今天我来给大家做一下Django的rest_framework的分页组件的分析;我的讲解的思路是这样的,分别使用APIview的视图类和基于ModelViewSet的视图类两种方式实现分页的功能,同时我也会介绍两个分页的类,PageNumberPagination类和LimitOffsetPagination,希望能对大家有所帮助!

  今天的博客主要的这样的,先讲解基于APIView类的两种分页类的实现方式,然后在讲解基于ModelViewSet类的两种分页类的实现方式

正文:

一、基于APIView的视图类,使用PageNumberPagination

1、先导入我们要用到的分页的类

from rest_framework.pagination import PageNumberPagination

  

2、下面我们来看下这个这个类的类是属性

class PageNumberPagination(BasePagination):
"""
A simple page number based style that supports page numbers as
query parameters. For example: http://api.example.org/accounts/?page=4
http://api.example.org/accounts/?page=4&page_size=100
"""
# The default page size.
# Defaults to `None`, meaning pagination is disabled.
page_size = api_settings.PAGE_SIZE django_paginator_class = DjangoPaginator # Client can control the page using this query parameter.
page_query_param = 'page'
page_query_description = _('A page number within the paginated result set.') # Client can control the page size using this query parameter.
# Default is 'None'. Set to eg 'page_size' to enable usage.
page_size_query_param = None
page_size_query_description = _('Number of results to return per page.') # Set to an integer to limit the maximum page size the client may request.
# Only relevant if 'page_size_query_param' has also been set.
max_page_size = None last_page_strings = ('last',) template = 'rest_framework/pagination/numbers.html' invalid_page_message = _('Invalid page.')

  

这里我们重点介绍一下类的属性,重点的参数如下,等下我们会测试的

3、然后看下类的paginate_queryset方法,这个方法主要就是用来显示数据的

    def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
page_size = self.get_page_size(request)
if not page_size:
return None paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages try:
self.page = paginator.page(page_number)
except InvalidPage as exc:
msg = self.invalid_page_message.format(
page_number=page_number, message=six.text_type(exc)
)
raise NotFound(msg) if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True self.request = request
return list(self.page)

  

4、PageNumberPagination用到知识点,我们已经讲解完了,下面我们介绍下如何使用,首先我们先继承一下PageNumberPagination,然后自定义我们的参数

class MyPageNumberPagination(PageNumberPagination):
page_size = 1
page_query_param = "mypage"
page_size_query_param = "size"
max_page_size = 4
last_page_strings = ('mylast',)

  

5、然后在视图类中使用我们自己写的分页类

class Book_cbv(APIView):
authentication_classes = []
# permission_classes = [SVIPpermission(),]
# throttle_classes = [throttlerate(),]
# parser_classes = []
def get(self,request): query_list = models.Book.objects.all()
mypageobj = MyPageNumberPagination()
obj = mypageobj.paginate_queryset(queryset=query_list,request=request,view=None)
bs = bookmodelserializer(obj,many=True,context={'request': request})

  

重点看下这里,关注一下paginate_queryset这个方法的参数,和源码中的参数对应一下

源码中的参数

6、下面我们测试一下

每页显示一条数据,显示第一页

每页显示1条数据,显示第二页

类中设定每页显示1条数据,我们临时修改为显示2条数据,显示第一页

类中设定每页显示1条数据,我们临时修改为显示5条数据,显示第一页,理论上5是不生效的,实际只显示了4条数据

经过测试,我们上面的四个参数都已经生效

最后在补充一点,上面的每页显示多少条的设置针对单个表生效,如何基于所有的表生效。

class PageNumberPagination(BasePagination):
"""
A simple page number based style that supports page numbers as
query parameters. For example: http://api.example.org/accounts/?page=4
http://api.example.org/accounts/?page=4&page_size=100
"""
# The default page size.
# Defaults to `None`, meaning pagination is disabled.
page_size = api_settings.PAGE_SIZE

  

然后看下api_setttings水里对象

api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)

  

看下APISettigns这个类

    def __init__(self, user_settings=None, defaults=None, import_strings=None):
if user_settings:
self._user_settings = self.__check_user_settings(user_settings)
self.defaults = defaults or DEFAULTS
self.import_strings = import_strings or IMPORT_STRINGS
self._cached_attrs = set()

  

到了这里,我们大致就知道了,我们需要进入我们的project的settings文件中进行设置

REST_FRAMEWORK = {
# "DEFAULT_AUTHENTICATION_CLASSES":(
# "app1.utils.Book_auther",
# ),
# "DEFAULT_PERMISSION_CLASSES_CLASSES": (
# "app1.utils.SVIPpermission",
# ),
# "DEFAULT_DEFAULT_THROTTLE_CLASSES_CLASSES": (
# "app1.utils.throttlerate",
# )
"PAGE_SIZE" : 2,
}

  

二、基于APIView的视图类,使用LimitOffsetPagination类

1、导入LimitOffsetPagination类

from rest_framework.pagination import LimitOffsetPagination

  

2、我们同样看下这个类的属性

class LimitOffsetPagination(BasePagination):
"""
A limit/offset based style. For example: http://api.example.org/accounts/?limit=100
http://api.example.org/accounts/?offset=400&limit=100
"""
default_limit = api_settings.PAGE_SIZE
limit_query_param = 'limit'
limit_query_description = _('Number of results to return per page.')
offset_query_param = 'offset'
offset_query_description = _('The initial index from which to return the results.')
max_limit = None
template = 'rest_framework/pagination/numbers.html'

  

重点看下下面几个属性

3、然后看下LimitOffsetPagination类的paginate_queryset的方法

    def paginate_queryset(self, queryset, request, view=None):
self.count = self.get_count(queryset)
self.limit = self.get_limit(request)
if self.limit is None:
return None self.offset = self.get_offset(request)
self.request = request
if self.count > self.limit and self.template is not None:
self.display_page_controls = True if self.count == 0 or self.offset > self.count:
return []
return list(queryset[self.offset:self.offset + self.limit])

  

4、然后我们看下如何在我们的视图类中使用这个分页插件,其实和前面的插件的用法是一样的,只是参数不一样而已

class Book_cbv(APIView):
authentication_classes = []
# permission_classes = [SVIPpermission(),]
# throttle_classes = [throttlerate(),]
# parser_classes = []
def get(self,request): query_list = models.Book.objects.all()
# mypageobj = MyPageNumberPagination()
# obj = mypageobj.paginate_queryset(queryset=query_list,request=request,view=None)
mypageobj = MyLimitOffsetPagination()
obj = mypageobj.paginate_queryset(queryset=query_list,request=request,view=None)
bs = bookmodelserializer(obj,many=True,context={'request': request}) return Response(bs.data)

  

重点是这里

5、最后我们测试一下

默认不传参数,每页显示2条

临时修改每页显示为1个,偏移量为1

临时修改每页显示1条,偏移量为2

三、基于ModelViewSet的视图类,实现分页功能

通过上面的讲解,我们知道两个分页的类就是参数不一样,使用的逻辑都一样,我们这里就不分开讲解2个类,只讲一下如何ModelViewSet类实现分页

1、先看下基于ModelViewSet的视图类

from rest_framework import viewsets

class AutherModelCBV(viewsets.ModelViewSet):
queryset = models.Auther.objects.all()
serializer_class = authermodelserializer

  

2、因为这个ModelViewSet这个类重写了list方法,分页肯定在list方法中,所以我们先要找到list方法,ModelViewSet这个类一共有4个父类

3、我们看下mixins.ListModelMixin这个类,因为list方法是在这个类中实现的,进入这个类,看下list方法

class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

  

4、重点看下paginate_queryset这个方法,首先要先找到这个方法

5、如果找这个方法呢,我们从最开始找这个方法

首先AutherModelCBV这个类没有这个方法

from rest_framework import viewsets

class AutherModelCBV(viewsets.ModelViewSet):
queryset = models.Auther.objects.all()
serializer_class = authermodelserializer

然后去ModelViewSet类中找这个方法,同样没有

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass

  

ModelViewSet这个类继承了有5个类,我们从左到右一个一个看,最终在GenericViewSet,我们看到这个类还继承了2个类

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass

  

再次从左到右依次查找paginate_queryset这个方法,最终下面这个类中找到这个方法

class GenericAPIView(views.APIView):

  

方法的源码如下

    def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)

  

那么这个paginator是什么呢,原来他是静态方法

    @property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator

  

到这里,我们就非常清楚的了,我们需要在我们自己的视图类中定义一个这样的属性,然后把我们的分页类赋值给pagination_class这个属性就可以了

6、然后看下在ModelViewSet类中如何操作

from rest_framework import viewsets

class AutherModelCBV(viewsets.ModelViewSet):
queryset = models.Auther.objects.all()
serializer_class = authermodelserializer
pagination_class = MyPageNumberPagination

  

重点看下这里

最后我们测试一下

下面这个是我们禁用分页的显示效果

下面开始启用分页的效果,显示第一页

显示第二页的效果

总结:至此,Django的Rest_framework的分页组件就介绍完了,大家有不清楚的,可以留言,我们共同进步。

Django的rest_framework的分页组件源码分析的更多相关文章

  1. Django框架之DRF 认证组件源码分析、权限组件源码分析、频率组件源码分析

    认证组件 权限组件 频率组件

  2. rest_framework解析器组件源码流程

    rest_framework解析器组件源码流程 解析器顾名思义就是对请求体进行解析.为什么要有解析器?原因很简单,当后台和前端进行交互的时候数据类型不一定都是表单数据或者json,当然也有其他类型的数 ...

  3. Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...

  4. element-ui 组件源码分析整理笔记目录

    element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...

  5. ceph-csi组件源码分析(1)-组件介绍与部署yaml分析

    更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi组件源码分析(1)-组件介绍与部署yaml分析 基于tag v3.0.0 ht ...

  6. 开源MyBatisGenerator组件源码分析

    开源MyBatisGenerator组件源码分析 看源码前,先了解Generator能做什么? MyBatisGenerator是用来生成mybatis的Mapper接口和xml文件的工具,提供多种启 ...

  7. Django REST framework —— 权限组件源码分析

    在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...

  8. Django REST framework —— 认证组件源码分析

    我在前面的博客里已经讲过了,我们一般编写API的时候用的方式 class CoursesView(ViewSetMixin,APIView): pass 这种方式的有点是,灵活性比较大,可以根据自己的 ...

  9. django Rest Framework----APIView 执行流程 APIView 源码分析

    在django—CBV源码分析中,我们是分析的from django.views import View下的执行流程,这篇博客我们介绍django Rest Framework下的APIView的源码 ...

随机推荐

  1. Java图片验证码学习

  2. Java自定义类加载器与双亲委派模型

    其实,双亲委派模型并不复杂.自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后copy一下就能用.但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制,这样显然不行.可是自定义类 ...

  3. Centos7.4安装配置haproxy和Keepalived

    系统版本是centos7.4的 [root@data-1-1 ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) [roo ...

  4. Ubuntu 下解压tar.xz方法

    参考地址:https://www.cnblogs.com/baby123/p/6611169.html

  5. pycharm 3.4 破解

    修改host,增加一行: 0.0.0.0 account.jetbrains.com 使用Activate code注册: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUl ...

  6. C++ Programming Language中的narrow_cast实现

    在C++中,各种数值类型的转化是C++编译过程中警告的主要来源,但是,很多时候,我们需要使用各种数值类型,例如我们用数组的某一位表示大小为对应序号的值,这种情况下,经常会涉及多种数值类型.根据C++ ...

  7. .net 调用 Matlab生成dll出现的问题(The type initializer for 'MathWorks​.MATLAB.NE​T.Utility.​MWMCR' threw an exception.)

    https://cn.mathworks.com/matlabcentral/answers/278399-i-get-an-error-saying-the-type-initializer-for ...

  8. CSS的background

    .block{ width: 200px; height: 200px; padding: 25px; background-image:linear-gradient(#58a,#58a) ,lin ...

  9. wordpress评论回复自动发邮件的功能

    A.插件流,可以说WP强大的插件功能的确能省事不少. 插件的办法一般是两步:第一实现成功发邮件,第二时间评论自动回复,这就需要用到两个插件,一个是Configure SMTP,一个是Mail To C ...

  10. 用户名、密码等15个常用的js正则表达式

    本文收集整理了15个常用的javaScript正则表达式,其中包括用户名.密码强度.整数.数字.电子邮件地址(Email).手机号码.身份证号.URL地址. IPv4地址. 十六进制颜色. 日期. Q ...