Django Rest Framework - 分页器

一、分页介绍

分页有三种方式

  • 普通分页,看第n页,每页显示m条数据;
  • 切割分页,在n个位置,向后查看m条数据;
  • 加密分页,这与普通分页方式相似,不过对url中的请求页码进行加密。

1 路由

1.1 主路由

1
2
3
4
5
6
from django.conf.urls import url, include
from django.urls import path

urlpatterns = [
url(r'^api/', include('api.urls')),
]

1.2 app路由

1
2
3
4
5
6
from django.conf.urls import url, include, re_path
from api import views

urlpatterns = [
re_path(r'^(?P<version>v\d)/users/$', views.UserView.as_view(), name='user'),
]

2 视图

在不使用django rest framework中的分页组件仍能够达到目的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from rest_framework.views import APIView
from rest_framework import serializers
from api.models import UserInfo
from rest_framework.pagination import PageNumberPagination


class MyUserSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo # models类名
# 方法一:生成所有数据库字段
fields = "__all__"


class UserView(APIView):
def get(self, request, *args, **kwargs):
# 1 获取所有数据
users = UserInfo.objects.all()
ser = MyUserSerializer(instance=users, many=True)
return HttpResponse(ser.data)

3 返回结果

二、PageNumberPagination

1 自定义分页类

1
2
3
4
5
6
7
from rest_framework.pagination import PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):
page_size = 2
max_page_size = 5
page_size_query_param = 'size'
page_query_param = 'page'
  • page_query_param:表示url中的页码参数
  • page_size_query_param:表示url中每页数量参数
  • page_size:表示每页的默认显示数量
  • max_page_size:表示每页最大显示数量,做限制使用,避免突然大量的查询数据,数据库崩溃

2 视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class PagerSerializer(serializers.ModelSerializer):
class Meta:
model = Role
fields = "__all__"

class MyPageNumberPagination(PageNumberPagination):
page_size = 2
page_size_query_param = "size"
max_page_size = 5
page_query_param = "page"

class UserView(APIView):
def get(self, request, *args, **kwargs):
# 1 获取所有数据
users = UserInfo.objects.all()
# 2 创建分页对象
pg = MyPageNumberPagination()
# 3 在数据库获取分页数据
users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
# 4 对数据进行序列化
ser = MyUserSerializer(instance=users_info, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
  • 首先需要实例化我们定义的分页类
  • 并且对实例化类进行传参控制
  • 最后将分页后的对象作序列化

3 测试结果

三、LimitOffsetPagination

1 自定义分页类

1
2
3
4
5
6
7
from rest_framework.pagination import LimitOffsetPagination

class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
  • default_limit:表示默认每页显示几条数据
  • limit_query_param:表示url中本页需要显示数量参数
  • offset_query_param:表示从数据库中的第几条数据开始显示参数
  • max_limit:表示每页最大显示数量,做限制使用,避免突然大量的查询数据,数据库崩溃

2 视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MyUserSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo # models类名
# 方法一:生成所有数据库字段
fields = "__all__"

class MyPageNumberPagination(LimitOffsetPagination):
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5

class UserView(APIView):
def get(self, request, *args, **kwargs):
# 1 获取所有数据
users = UserInfo.objects.all()
# 2 创建分页对象
pg = MyPageNumberPagination()
# 3 在数据库获取分页数据
users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
# 4 对数据进行序列化
ser = MyUserSerializer(instance=users_info, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
  • 首先需要实例化我们定义的分页类
  • 并且对实例化类进行传参控制
  • 最后将分页后的对象作序列化

3 测试结果

四、使用加密分页

如果使用普通分页时,由于向用户提供了可选参数page,用户可以直接跳到数据分页之后的任意页码。但是这样做的后果就是,数据库的负载变大,返回结果的效率缓慢。但是一旦使用加密之后,虽然提供可选参数cursor,但是对页码进行加密,用户无法知道当前页,而是以上一页下一页的方式翻阅数据。有效避免了数据库的负荷。但是就需要向用户提供上一页下一页的url

1 自定义分页类

1
2
3
4
from rest_framework.pagination import LimitOffsetPagination

class MyCursorPagination(CursorPagination):
ordering = 'id'
  • ordering:表示返回数据的排序方式

2 视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MyUserSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo # models类名
# 方法一:生成所有数据库字段
fields = "__all__"

class MyPageNumberPagination(CursorPagination):
ordering = 'id'

class UserView(APIView):
def get(self, request, *args, **kwargs):
# 1 获取所有数据
users = UserInfo.objects.all()
# 2 创建分页对象
pg = MyPageNumberPagination()
# 3 在数据库获取分页数据
users_info = pg.paginate_queryset(queryset=users, request=request, view=self)
# 4 对数据进行序列化
ser = MyUserSerializer(instance=users_info, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
  • 首先需要实例化我们定义的分页类
  • 并且对实例化类进行传参控制
  • 最后将分页后的对象作序列化
  • 由于要想用户提供可用的上下页接口,所以只能用pg.get_paginated_response(ser.data)做返回

3 测试结果

五、总结

三种分页中,普通分页与django中的分页基本没有区别。不过要做分页返回给前端数据,就要从数据库中取出数据,然后在做分页序列化。如果用户一下在前几页请求数据库中的最后几页数据,对查询数据库的时延,对数据库的负载较大,就会出现问题,这个时候就可以使用加密分页,限制用户的访问,只提供前一页和后一页的接口。