REST framework提供了分页的支持,内置的分页器需要继承 GenericAPIView 和 ListModelMixin,对查询所有接口进行分页。
1. 可以自己继承 PageNumberPagination 设置属性,如下示例
from rest_framework.pagination import PageNumberPagination
class CommonPageNumberPagination(PageNumberPagination):
page_size = 3
page_size_query_param = 'size'
max_page_size = 5
page_query_param = 'page'
属性 | 解释 |
---|---|
page_size | 每页数目 |
page_query_param | 前端发送的页数关键字名,默认为”page” |
page_size_query_param | 前端发送的每页数目关键字名,默认为None |
max_page_size | 前端最多能设置的每页数量 |
只要在视图函数中添加以下配置
pagination_class = CommonPageNumberPagination
如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
http://127.0.0.1:8000/students/?page=2&size=30 # 使用 GET 方法
在路由中添加的 page 表示页码,size 表示一页展示的条数
2. 也可以直接在 setting 配置文件中全局添加,如下所示
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
1. 方法一,继承 LimitOffsetPagination 定义属性
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
属性 | 解释 |
---|---|
default_limit | 默认展示条数,默认值与 PAGE_SIZE 设置一致 |
limit_query_param | limit 参数名,默认 ’limit’,控制取的条数 |
offset_query_param | offset 参数名,默认 ’offset’。控制从第 X 个位置偏移多少开始取数据 |
max_limit | 最大limit限制,默认 None |
只要在视图函数中添加以下配置
pagination_class = CommonLimitOffsetPagination
如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
http://127.0.0.1:8000/students/?limit=2&offset=3 # 使用 GET 方法
在路由中添加的 limit 表示一个页码展示的取出条数,offset 表示偏移数。例如上面的路由是每页展示 2 条数据,并且是从第 3 条数据开始展示 2 条,也就是展示的是 第 4、5 条数据。
1. 方法一,继承 CursorPagination定义属性
class CommonCursorPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 3
ordering = 'id'
属性 | 解释 |
---|---|
cursor_query_param | 默认查询字段,类似于 cursor = xxx,但是该值是随机的。 |
page_size | 每页展示的数目 |
ordering | 按什么排序,一般使用 id,需要注意其必须是表中有的字段 |
只要在视图函数中添加以下配置
pagination_class = CommonCursorPagination
如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
前面的使用内置分页的视图函数都需要继承 GenericAPIView、ListModelMixin,我们可以自己编写继承 APIView 的视图函数实现分页。
class MyPage(APIView):
def get(self, request):
# 获取所有数据集
books = models.Book.objects.all()
# 对数据集进行分页,可以是自己配置了参数的分页器
paginator = CommonPageNumberPagination()
# 获取分页过后的数据
qs = paginator.paginate_queryset(books, request, self)
# 对数据进行序列化,多条数据需要添加 many=True
res = serializer.BookSerializer(qs, many=True)
# 返回的方式一,只返回分页后的结果
# return Response(res.data)
# 返回方式二,自己配置返回的其他信息,例如上一页下一页
# return Response({
# 'count': books.count(),
# 'next': paginator.get_next_link(),
# 'previous': paginator.get_previous_link(),
# 'results': res.data
# })
# 返回方式三,使用方法自动返回类似于方式二的内容
return paginator.get_paginated_response(res.data)
1. path('mypage/', BookViews.MyPage.as_view({'get': 'get'})),
2.
from django.urls import path
from app01.view import BookViews
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('mypage', BookViews.MyPage, 'mypage')
urlpatterns = []
urlpatterns += router.urls
3. 添加 @action(methods=['get',], detail=False)
这么编写的方式可以查看源码解析。
源码解析
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
def paginate_queryset(self, queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)
@property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
def get_paginated_response(self, data):
return Response(OrderedDict([
('count', self.page.paginator.count),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))