在前面的DRF系列教程中,以博客为例介绍了序列化器, 使用基于类的视图APIView和ModelViewSet开发了针对文章资源进行增删查改的完整API接口,并详细对权限和认证(含jwt认证)进行了总结与演示。在本篇文章中将向演示如何在Django REST Framework中使用分页。
参考文章:
3、DRF实战总结:基于类的视图APIView, GenericAPIView和GenericViewSet视图集(附源码)_SteveRocket的博客-CSDN博客
4、DRF实战总结:序列化器(Serializer)、数据验证、重写序列化器方法详解(附源码)_SteveRocket的博客-CSDN博客
https://blog.csdn.net/zhouruifu2015/article/details/129965342
https://blog.csdn.net/zhouruifu2015/article/details/129965353
DRF中的分页是指将数据按照一定数量分割成多页的显示方法。每页显示一定的数据量,可以通过用户点击或者其他手段进行翻页操作。DRF分页的作用是在返回数据时,将数据分页显示,避免一次性返回大量数据导致网络传输不稳定、用户体验不佳等问题。
当的数据库数据量非常大时,如果一次将这些数据查询出来, 必然加大了服务器内存的负载,降低了系统的运行速度。一种更好的方式是将数据分段展示给用户。如果用户在展示的分段数据中没有找到自己的内容,可以通过指定页码或翻页的方式查看更多数据,直到找到自己想要的内容为止。
Django REST Framework提供3种分页类:
1. PageNumberPagination类
简单分页器。非常常用的一种分页方式,其作用是将数据序列化后,返回符合要求的页码以及页码对应的数据列表。
支持用户按?page=3这种方式查询,可以通过page_size这个参数手动指定每页展示给用户数据的数量。它还支持用户按?page=3&size=10这种更灵活的方式进行查询,这样用户不仅可以选择页码,还可以选择每页展示数据的数量。对于第二种情况,通常还需要设置max_page_size这个参数限制每页展示数据的最大数量,以防止用户进行恶意查询(比如size=10000), 这样一页展示1万条数据将使分页变得没有意义。
2. LimitOffsetPagination类
偏移分页器。作用是通过传入的"limit"和"offset"参数实现数据分页,其中"limit"为每页数据数,"offset"是从第几个数据开始返回。
支持用户按?limit=20&offset=100这种方式进行查询。offset是查询数据的起始点,limit是每页展示数据的最大条数,类似于page_size。当使用这个类时,通常还需要设置max_limit这个参数来限制展示给用户数据的最大数量。
3. CursorPagination类
加密分页器。按照给定的排序方式将数据分页,每一页的分界点是另一页中最后一个数据的主键值。这种方式可以实现更为灵活的分页,因为它不受 limit 的限制,可以方便的实现“无限滚动式”或“加载更多”式的交互。
这是DRF提供的加密分页查询,仅支持用户按响应提供的上一页和下一页链接进行分页查询,每页的页码都是加密的。使用这种方式进行分页需要的模型有"created"这个字段,否则要手动指定ordering排序才能进行使用。
DRF中使用默认分页类的最简单方式就是在settings.py中进行全局配置,如下所示:
展示效果如下,每页展示两条记录, 不支持用户指定每页展示数据的数量。
如何查询一个超出内容数量的页数,则会提示Invalid page
但是如果希望用户按?page=3&size=10这种更灵活的方式进行查询,就要进行个性化定制。在实际开发过程中,定制比使用默认的分页类更常见,具体做法如下。
在app目录下新建pagination.py, 添加如下代码:
#drf_pro/pagination.py
自定义了一个MyPageNumberPagination类,该类继承了PageNumberPagination类。通过page_size设置了每页默认展示数据的条数,通过page_size_query_param设置了每页size的参数名以及通过max_page_size设置了每页可以展示的最大数据条数。
使用自定义的分页类
在基于类的视图中,可以使用pagination_class这个属性使用自定义的分页类,如下所示:
添加urls
展示效果如下所示:
当然定制分页类不限于指定page_size和max_page_size这些属性,还可以改变响应数据的输出格式。比如这里希望把next和previous放在一个名为links的key里,可以修改MyPageNumberPagination类,重写get_paginated_response方法:
新的展示效果如下所示:
注意:重写get_paginated_response方法非常有用,还可以给分页响应数据传递额外的内容,比如code状态码等等。
前面的例子中只在单个基于类的视图或视图集中使用到了分页类,还可以修改settings.py全局使用自定义的分页类,展示效果是一样的。
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'blog.pagination.MyPageNumberPagination',
}
使用这个分页类最简单的方式就是在settings.py中进行全局配置,如下所示:
展示效果如下所示,从2页起,每页2条
也可以自定义MyLimitOffsetPagination类,在单个视图或视图集中使用,或者全局使用。
展示效果如下,从第2条数据查起,每页展示2条。
全局使用
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 2
}
展示效果如下所示:
使用CursorPagination类需要的模型里有created这个字段,否则需要手动指定ordering字段。这是因为CursorPagination类只能对排过序的查询集进行分页展示。Article模型只有create_date字段,没有created这个字段,所以会报错。
为了解决这个问题,需要自定义一个MyCursorPagination类,手动指定按create_date排序, 如下所示:
#drf_pro/pagination.py
修改settings.py, 使用自己定义的分页类。
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'blog.pagination.MyArticleCursorPagination',
}
响应效果如下所示,将得到previous和next分页链接。页码都加密了, 链接里不再显示页码号码。默认每页展示3条记录
如果使用?page_size=2进行查询,每页将得到两条记录。
当然由于这个ordering字段与模型相关,并不推荐全局使用自定义的CursorPagination类,更好的方式是在GenericsAPIView或视图集viewsets中通过pagination_class属性指定,如下所示:
注意pagination_class属性仅支持在genericsAPIView和视图集viewset中配置使用。如果使用函数或简单的APIView开发API视图,那么需要对数据进行手动分页,如下示例所示:
代码示例:https://download.csdn.net/download/zhouruifu2015/87657280