分页围绕三类
a. 分页看第n页, 每页显示的n条数据 PageNumberPagination
b. 在n个位置,向后查看n条数据 LimitOffsetPagination
c. 加密分页 上一页和下一页CursorPagination 用户不能随便输入页码,页码已被这个类加密 ,这个类做的好,它把当前页的最大的id和最小的id的记住,下次在分页的时候根据最大和最小id来,如果不加密的话,假如数据库数据非常多的话,用户万一从当前页直接输入“四九”页,这时候应该数据响应速度慢,MySQL服务器压力太大了。
举例:
表设计
1 from django.db import models 2 3 4 class UserGroup(models.Model): 5 title = models.CharField(max_length=32) 6 7 8 class UserInfo(models.Model): 9 user_type_choices = ( 10 (1, '普通用户'), 11 (2, 'vip'), 12 (3, 'svip'), 13 ) 14 user_type = models.IntegerField(choices=user_type_choices) 15 username = models.CharField(max_length=32, unique=True) 16 password = models.CharField(max_length=64) 17 group = models.ForeignKey('UserGroup', on_delete=models.CASCADE) 18 roles = models.ManyToManyField('Role') 19 20 21 class UserToken(models.Model): 22 user = models.OneToOneField(to='UserInfo', on_delete=models.CASCADE) 23 token = models.CharField(max_length=64) 24 25 26 class Role(models.Model): 27 title = models.CharField(max_length=32)
路由:
1 from django.contrib import admin 2 from django.urls import path, re_path, include 3 4 urlpatterns = [ 5 path('admin/', admin.site.urls), 6 re_path('api/', include('api.urls')), 7 ]
分发:
1 from django.urls import path, re_path, include 2 from api import views 3 4 urlpatterns = [ 5 # 分页 6 re_path('(?P<version>[v1|v2]+)/page1/$', views.Page1View.as_view()), 7 ]
视图以及序列化
1 class PagerSerializer(serializers.ModelSerializer): 2 class Meta: 3 model = models.Role 4 fields = '__all__' 5 6 7 from rest_framework.response import Response 8 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination 9 10 11 class MyPageNumberPagination(PageNumberPagination): 12 """ 13 http://api.example.org/accounts/?page=4 14 http://api.example.org/accounts/?page=4&page_size=100 15 """ 16 page_size = 2 17 # 自己通过传参定制一页显示多少数据 18 # http://127.0.0.1:8000/api/v1/page1/?page=2&size=3 19 page_size_query_param = 'size' 20 max_page_size = 5 21 22 page_query_param = 'page' 23 24 25 class MyLimitOffsetPagination(LimitOffsetPagination): 26 """ 27 http://api.example.org/accounts/?limit=100 28 http://api.example.org/accounts/?offset=400&limit=100 29 """ 30 default_limit = 2 31 limit_query_param = 'limit' 32 offset_query_param = 'offset' 33 max_limit = 5 34 35 36 class MyCursorPagination(CursorPagination): 37 """ 38 "next": "http://127.0.0.1:8000/api/v1/page1/?cursor=cD02", 39 "previous": "http://127.0.0.1:8000/api/v1/page1/?cursor=cj0xJnA9NQ%3D%3D", 40 """ 41 cursor_query_param = 'cursor' 42 page_size = 2 43 ordering = 'id' 44 page_size_query_param = None 45 max_page_size = None 46 47 48 class Page1View(APIView): 49 def get(self, request, *args, **kwargs): 50 roles = models.Role.objects.all() 51 52 # pg = PageNumberPagination() 53 # pg = MyPageNumberPagination() 54 # pg = MyLimitOffsetPagination() 55 pg = MyCursorPagination() 56 57 # 在数据库中获取分页的数据 58 pg_roles = pg.paginate_queryset(queryset=roles, request=request, view=self) 59 # 对数据序列化 60 ser = PagerSerializer(instance=pg_roles, many=True) 61 62 # 返回两种方式 63 # ret = ser.data 64 # return Response(ret) 65 # 帮我们做了上一页下一页的 66 # "count": 8, 67 # "next": "http://127.0.0.1:8000/api/v1/page1/?page=3&size=3", 68 # "previous": "http://127.0.0.1:8000/api/v1/page1/?size=3", 69 ret = pg.get_paginated_response(ser.data) 70 return ret
全局也可配置:
1 REST_FRAMEWORK = { 2 # 分页 3 'PAGE_SIZE': 2 4 }
内置的分页类:
我觉得这个三个已经够用了。CursorPagination这个重要,而且涉及到了性能。