我不确定这是否是完全正确的方法,但它可以满足我的需要。它使用 Django Paginator 和自定义序列化程序。
这是我的视图类,它检索对象以进行序列化
class CourseListView(AuthView):
def get(self, request, format=None):
"""
Returns a JSON response with a listing of course objects
"""
courses = Course.objects.order_by('name').all()
serializer = PaginatedCourseSerializer(courses, request, 25)
return Response(serializer.data)
这是使用我的 Course 序列化器的组合序列化器。
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
class PaginatedCourseSerializer():
def __init__(self, courses, request, num):
paginator = Paginator(courses, num)
page = request.QUERY_PARAMS.get('page')
try:
courses = paginator.page(page)
except PageNotAnInteger:
courses = paginator.page(1)
except EmptyPage:
courses = paginator.page(paginator.num_pages)
count = paginator.count
previous = None if not courses.has_previous() else courses.previous_page_number()
next = None if not courses.has_next() else courses.next_page_number()
serializer = CourseSerializer(courses, many=True)
self.data = {'count':count,'previous':previous,
'next':next,'courses':serializer.data}
这给了我一个类似于旧分页器给出的行为的结果。
{
"previous": 1,
"next": 3,
"courses": [...],
"count": 384
}
我希望这有帮助。我仍然认为必须有一个更好的方法来使用新的 API 来做到这一点,但它只是没有很好地记录下来。如果我想出更多的东西,我会编辑我的帖子。
编辑
我想我已经找到了一种更好、更优雅的方法来做到这一点,因为我创建了自己的自定义分页器来获得像以前使用旧的分页序列化器类一样的行为。
这是一个自定义分页器类。我重载了响应和下一页方法以获得我想要的结果(即?page=2
,而不是完整的 url)。
from rest_framework.response import Response
from rest_framework.utils.urls import replace_query_param
class CustomCoursePaginator(pagination.PageNumberPagination):
def get_paginated_response(self, data):
return Response({'count': self.page.paginator.count,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'courses': data})
def get_next_link(self):
if not self.page.has_next():
return None
page_number = self.page.next_page_number()
return replace_query_param('', self.page_query_param, page_number)
def get_previous_link(self):
if not self.page.has_previous():
return None
page_number = self.page.previous_page_number()
return replace_query_param('', self.page_query_param, page_number)
然后我的课程视图与您实现它的方式非常相似,只是这次使用了自定义分页器。
class CourseListView(AuthView):
def get(self, request, format=None):
"""
Returns a JSON response with a listing of course objects
"""
courses = Course.objects.order_by('name').all()
paginator = CustomCoursePaginator()
result_page = paginator.paginate_queryset(courses, request)
serializer = CourseSerializer(result_page, many=True)
return paginator.get_paginated_response(serializer.data)
现在我得到了我正在寻找的结果。
{
"count": 384,
"next": "?page=3",
"previous": "?page=1",
"courses": []
}
我仍然不确定这对 Browsable API 是如何工作的(我不使用 drf 的这个功能)。我认为您也可以为此创建自己的自定义类。我希望这有帮助!