django 的drf中自带有list的分页,部分源码如下:
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 get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
@property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
通过分析源码可以看到list的分页返回是取pagination_class里的get_paginated_response方法
配置方法一:
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination
class HomeAPIView(viewsets.ModelViewSet):
queryset = Home.objects.all()
pagination_class = CoursePageNumberPagination
CoursePageNumberPagination里的get_paginated_response方法如下:
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)
]))
配置方法二:
class GenericAPIView(views.APIView):
queryset = None
serializer_class = None
lookup_field = 'pk'
lookup_url_kwarg = None
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
配置如下:
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "component.drf.pagination.CustomPageNumberPagination",
}
再往深点看其实可以看到drf是封装了django.core.paginator
个人开发的时候,有时候写序列化器时,字段查询比较繁琐,就想自己查到数据自己去封装,但是又想格式和drf风格差不多,就自定义封装分页。
from django.core.paginator import Paginator
def my_paginator_response(current_page, page_size, objs):
"""自定义包装返回参数"""
current_page = int(current_page)
paginator = Paginator(objs, page_size)
if current_page not in paginator.page_range:
current_page = 1
return dict(
page=current_page,
total_page=paginator.num_pages,
count=paginator.count,
previous=paginator.page(current_page).previous_page_number()
if paginator.page(current_page).has_previous()
else None,
next=paginator.page(current_page).next_page_number() if paginator.page(current_page).has_next() else None,
items=paginator.page(current_page).object_list,
)
使用案例:
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import Q
class GenericAPIView(views.APIView):
queryset = Home.objects.all()
@action(methods=["get"], detail=False)
def get_homes(self, request, *args, **kwargs):
home_name = request.query_params.get("home_name")
current_page = request.query_params.get("current_page", 1)
page_size = request.query_params.get("page_size", 10)
q = Q()
if task_name:
q &= Q(home_name__icontains=str(home_name))
checktasks = CheckTask.objects.filter(q)
resp_data = my_paginator_response(current_page,page_size,checktasks)
# 如果需要特殊序列化数据可以取出来
for item in resp_data['items']:
# do somethings
pass
return Response(resp_data)