Django REST Framework 分页(Pagination)详解
在前面的DRF系列教程中,我们以博客为例介绍了序列化器, 使用基于类的视图APIView和ModelViewSet开发了针对文章资源进行增删查改的完整API端点,并详细对权限和认证(含jwt认证)进行了总结与演示。在本篇文章中我们将向你演示如何在Django REST Framework中使用分页。
分页
为什么要分页"created"这个字段,否则你要手动指定ordering排序才能进行使用。
使用PageNumberPagination类
DRF中使用默认分页类的最简单方式就是在settings.py中进行全局配置,如下所示:
REST_FRAMEWORK ={ 'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE':2 }
展示效果如下,每页展示两条记录, 不支持用户指定每页展示数据的数量。
但是如果你希望用户按"htmlcode">
from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 # default page size page_size_query_param = 'size' # "htmlcode">from rest_framework import viewsets from .pagination import MyPageNumberPagination class ArticleViewSet(viewsets.ModelViewSet): # 用一个视图集替代ArticleList和ArticleDetail两个视图 queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = MyPageNumberPagination # 自行添加,将request.user与author绑定 def perform_create(self, serializer): serializer.save(author=self.request.user) # 自行添加,将request.user与author绑定 def perform_update(self, serializer): serializer.save(author=self.request.user)展示效果如下所示:
当然定制分页类不限于指定page_size和max_page_size这些属性,你还可以改变响应数据的输出格式。比如我们这里希望把next和previous放在一个名为links的key里,我们可以修改MyPageNumberPagination类,重写get_paginated_response方法:
from rest_framework.pagination import PageNumberPagination from rest_framework.response import Response class MyPageNumberPagination(PageNumberPagination): page_size = 2 # default page size page_size_query_param = 'size' # "text-align: center">注意:重写get_paginated_response方法非常有用,你还可以给分页响应数据传递额外的内容,比如code状态码等等。
前面的例子中我们只在单个基于类的视图或视图集中使用到了分页类,你还可以修改settings.py全局使用你自定义的分页类,如下所示。展示效果是一样的,我们就不详细演示了。
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'blog.pagination.MyPageNumberPagination', }使用LimitOffsetPagination类
使用这个分页类最简单的方式就是在settings.py中进行全局配置,如下所示:
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination' }展示效果如下所示,从第6条数据查起,每页展示2条。
你也可以自定义MyLimitOffsetPagination类,在单个视图或视图集中使用,或者全局使用。
from rest_framework.pagination import LimitOffsetPagination class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 5 # default limit per age limit_query_param = 'limit' # default is limit offset_query_param = 'offset' # default param is offset max_limit = 10 # max limit per age使用CursorPagination类
全局使用
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination', 'PAGE_SIZE': 2 }展示效果如下所示:
什么"htmlcode">
from rest_framework.pagination import CursorPagination class MyArticleCursorPagination(CursorPagination): page_size = 3 # Default number of records per age page_size_query_param = 'page_size' cursor_query_param = 'cursor' # Default is cursor ordering = '-create_date'修改settings.py, 使用自己定义的分页类。
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'blog.pagination.MyArticleCursorPagination', }响应效果如下所示,你将得到previous和next分页链接。页码都加密了, 链接里不再显示页码号码。默认每页展示3条记录, 如果使用"text-align: center">
当然由于这个ordering字段与模型相关,我们并不推荐全局使用自定义的CursorPagination类,更好的方式是在GenericsAPIView或视图集viewsets中通过pagination_class属性指定,如下所示:
from rest_framework import viewsets from .pagination import MyArticleCursorPagination class ArticleViewSet(viewsets.ModelViewSet): # 用一个视图集替代ArticleList和ArticleDetail两个视图 queryset = Article.objects.all() serializer_class = ArticleSerializer pagination_class = MyArticleCursorPagination # 自行添加,将request.user与author绑定 def perform_create(self, serializer): serializer.save(author=self.request.user) # 自行添加,将request.user与author绑定 def perform_update(self, serializer): serializer.save(author=self.request.user)函数类视图中使用分页类
注意pagination_class属性仅支持在genericsAPIView和视图集viewset中配置使用。如果你使用函数或简单的APIView开发API视图,那么你需要对你的数据进行手动分页,一个具体使用例子如下所示:
from rest_framework.pagination import PageNumberPagination class ArticleList0(APIView): """ List all articles, or create a new article. """ def get(self, request, format=None): articles = Article.objects.all() page = PageNumberPagination() # 产生一个分页器对象 page.page_size = 3 # 默认每页显示的多少条记录 page.page_query_param = 'page' # 默认查询参数名为 page page.page_size_query_param = 'size' # 前台控制每页显示的最大条数 page.max_page_size = 10 # 后台控制显示的最大记录条数,防止用户输入的查询条数过大 ret = page.paginate_queryset(articles, request) serializer = ArticleSerializer(ret, many=True) return Response(serializer.data)小结
本文总结了DRF提供的3种分页类并详细演示了如何使用它们,你学会了吗?
下一篇:python 爬虫网页登陆的简单实现
在此次发布会上,英特尔还发布了全新的全新的酷睿Ultra Meteor Lake NUC开发套件,以及联合微软等合作伙伴联合定义“AI PC”的定义标准。