分页
# 1. 分页介绍
当对于数据量的大的时候,我们在一个页面显示不下,这个时候我们就需要采用分页的操作。
分页方式:
- 普通分页:看第 n 页,每页显示 m 条数据;
- 切割分页:在 n 个位置,向后查看 m 条数据;
- 加密分页:这与普通分页方式相似,不过对 URL 中的请求页码进行 加密。
# 2 全局分页
我们可以在配置文件中设置全局的分页方式,如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
1
2
3
4
2
3
4
注意:如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
1
# 3. 局部分页
# ***************** 分页 ********************
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from . import models
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__'
class PageGroupView(APIView):
def get(self, request, *args, **kwargs):
roles = models.Role.objects.all()
pg = PageNumberPagination()
data = pg.paginate_queryset(queryset=roles,request=request,view=self)
pg_data = PageSerializer(instance=data, many=True)
return Response(pg_data.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
url(r'^(?P<version>[v1|v2]+)/page1/$', views.PageGroupView.as_view()), # 分页
1
# 4. 可选分页器(自定义分页)
# PageNumberPagination
可以在子类中定义的属性:
- page_size 每页数目
- page_query_param 前端发送的页数关键字名,默认为"page"
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量
分页,看第n页,每页显示n条数据;
class MyPageNumberPagination(PageNumberPagination):
"""
http://127.0.0.1:8000/api/v1/page1/?page=2
"""
page_size = 2
page_size_query_param = 'page_size' # http://127.0.0.1:8000/api/v1/page1/?page=1&page_size=6 重新指定每页显示的条数
max_page_size = 5
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__'
class PageGroupView(APIView):
def get(self, request, *args, **kwargs):
# 获取使用数据
roles = models.Role.objects.all()
# 创建分页对象
pg = MyPageNumberPagination()
# 在数据库中获取分页的数据
data = pg.paginate_queryset(queryset=roles,request=request,view=self)
# 对数据进行序列化
pg_data = PageSerializer(instance=data, many=True)
return Response(pg_data.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# LimitOffsetPagination
可以在子类中定义的属性:
- default_limit 默认限制,默认值与
PAGE_SIZE
设置一直 - limit_query_param limit参数名,默认'limit'
- offset_query_param offset参数名,默认'offset'
- max_limit 最大limit限制,默认None
分页,在n个位置,向后查看n条数据;
class MyLimitOffsetPagination(LimitOffsetPagination):
"""
http://127.0.0.1:8000/api/v1/page1/?offset=3&limit=4 # 第三页显示4条数据
"""
default_limit = 2 # 默认为每页2条
limit_query_param = 'limit' # 第几页
offset_query_param = 'offset' # 显示几条数据
max_limit = 5 # 最大每页5条
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__'
class PageGroupView(APIView):
def get(self, request, *args, **kwargs):
# 获取使用数据
roles = models.Role.objects.all()
# 创建分页对象
# pg = MyPageNumberPagination()
pg = MyLimitOffsetPagination()
# 在数据库中获取分页的数据
data = pg.paginate_queryset(queryset=roles, request=request, view=self)
# 对数据进行序列化
pg_data = PageSerializer(instance=data, many=True)
# return Response(pg_data.data)
return pg.get_paginated_response(pg_data.data) # 添加一些参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# CursorPagination(加密分页)
加密分页,上一页和下一页
class MyCursorPagination(CursorPagination):
"""
加密分页
"next": "http://127.0.0.1:8000/api/v1/page1/?cursor=cD00",
"previous": "http://127.0.0.1:8000/api/v1/page1/?cursor=cj0xJnA9Mw%3D%3D",
"""
cursor_query_param = 'cursor' # 查询参数
page_size = 2 # 每页二条
ordering = 'id' # 以id查询 -id:表示逆序
page_size_query_param = None # 名称
max_page_size = None # 最大条数
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__'
class PageGroupView(APIView):
def get(self, request, *args, **kwargs):
# 获取使用数据
roles = models.Role.objects.all()
# 创建分页对象
# pg = MyPageNumberPagination()
# pg = MyLimitOffsetPagination()
pg = MyCursorPagination()
# 在数据库中获取分页的数据
data = pg.paginate_queryset(queryset=roles, request=request, view=self)
# 对数据进行序列化
pg_data = PageSerializer(instance=data, many=True)
# return Response(pg_data.data)
return pg.get_paginated_response(pg_data.data) # 添加一些参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 自定义示例
class MyPagination(PageNumberPagination):
"""分页器"""
page_size = 10 # 每页数量
page_size_query_param = 'page_size' # 每页条数
page_query_param = "page" # 页码
max_page_size = None # 最大页码数限制
def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
page_size = self.get_page_size(request)
if not page_size:
return None
paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages
try:
self.page = paginator.page(page_number)
except InvalidPage as exc:
msg = self.invalid_page_message.format(
page_number=page_number, message=str(exc)
)
raise NotFound(msg)
if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
self.request = request
return list(self.page)
def get_page_size(self, request):
"""重写获取page_size的函数"""
if self.page_size_query_param:
if request.query_params.get(self.page_size_query_param) == '-1':
self.page_size = None
else:
try:
return _positive_int(
request.query_params[self.page_size_query_param],
strict=True,
cutoff=self.max_page_size
)
except (KeyError, ValueError):
pass
return self.page_size
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
编辑 (opens new window)