为什么要使用分页?
我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输过程中耗时也会比较大。
通常我们会希望一部分一部分去请求数据,也就是我们常说的一页一页获取数据并展示出来。
rest framework中提供了三种分页模式
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
全局配置
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 100 }
局部配置
class PublisherViewSet(ModelViewSet): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer pagination_class = PageNumberPagination # 注意不是列表(只能有一个分页模式)
第一种: PageNumberPagination
按页码数分页,第n页,每页显示m条数据
例如:http://127.0.0.1:8000/api/article/?page=2&size=1
分页器
class MyPageNumber(PageNumberPagination): page_size = 2 # 每页显示多少条 page_size_query_param = 'size' # URL中每页显示条数的参数KEY
page_query_param = 'page' # URL中页码的参数 max_page_size = None # 最大页码数限制
视图
class ArticleList(APIView): def get(self, request, *args, **kwargs): res = {"code": 0} article_list = models.Article.objects.all().order_by("id") # 分页 page_obj = MyPageNumber() page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self) ser_obj = ArticleSerializer(page_article, many=True) res["data"] = ser_obj.data return Response(res)
返回带页码连接的响应
class ArticleList(APIView): def get(self, request, *args, **kwargs): res = {"code": 0} article_list = models.Article.objects.all().order_by("id") # 分页 page_obj = MyPageNumber() page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self) ser_obj = ArticleSerializer(page_article, many=True) res["data"] = ser_obj.data return page_obj.get_paginated_response(res)
第二种: LimitOffsetPagination
分页,在n位置,向后查看m条数据,数据库查询时效率较高
例如:http://127.0.0.1:8000/api/article/?offset=2&limit=2
分页器
# offset分页 class MyLimitOffset(LimitOffsetPagination): default_limit = 1 limit_query_param = 'limit' offset_query_param = 'offset' max_limit = 999
视图
class ArticleList(APIView): def get(self, request, *args, **kwargs): res = {"code": 0} article_list = models.Article.objects.all().order_by("id") # 分页 page_obj = MyLimitOffset() page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self) ser_obj = ArticleSerializer(page_article, many=True) res["data"] = ser_obj.data return page_obj.get_paginated_response(res) 复制代码
自定义
# 当有特殊的配置需要代替默认的配置时,我们就自己写个类 class MyLimitPager(LimitOffsetPagination): limit_query_param = 'page_size' # 自定义limit的参数key pass
第三种: CursorPagination
加密分页,把上一页和下一页的id值记住
分页器
# 加密分页 class MyCursorPagination(CursorPagination): cursor_query_param = 'cursor' page_size = 1 ordering = '-id' # 重写要排序的字段
视图
class ArticleList(APIView): def get(self, request, *args, **kwargs): res = {"code": 0} article_list = models.Article.objects.all().order_by("id") # 分页 page_obj = MyCursorPagination() page_article = page_obj.paginate_queryset(queryset=article_list, request=request, view=self) ser_obj = ArticleSerializer(page_article, many=True) res["data"] = ser_obj.data # return Response(res) return page_obj.get_paginated_response(res)
解析器和渲染器
配置
# 解析器 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ), # 渲染器 # 你要页面 我就给你页面 # 你要JSON格式的数据 我就给你JSON格式的数据 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', # 'rest_framework.renderers.BrowsableAPIRenderer', ),