Python Django Rest Framework 3.1中断分页。分页序列化程序
我刚刚更新到Django Rest Framework 3.1,似乎一切都糟透了 在我的Python Django Rest Framework 3.1中断分页。分页序列化程序,python,django,pagination,django-rest-framework,django-pagination,Python,Django,Pagination,Django Rest Framework,Django Pagination,我刚刚更新到Django Rest Framework 3.1,似乎一切都糟透了 在我的serializers.py中,我有以下代码: class TaskSerializer(serializers.ModelSerializer): class Meta: model = task exclude = ('key', ...) class PaginatedTaskSerializer(pagination.PaginationSerializer): cl
serializers.py中,我有以下代码:
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = task
exclude = ('key', ...)
class PaginatedTaskSerializer(pagination.PaginationSerializer):
class Meta:
object_serializer_class = TaskSerializer
这一切都很顺利。现在随着3.1的发布,我找不到如何做同样事情的例子,因为分页序列化器已经不存在了。
我曾尝试将PageNumberPagination
子类化,并使用其默认的paginate\u queryset
和get\u paginated\u response
方法,但我无法再将其结果序列化
换句话说,我的问题是我不能再这样做了:
class Meta:
object_serializer_class = TaskSerializer
有什么想法吗
提前感谢我不确定这是否是完全正确的方法,但它适合我的需要。它使用Django Paginator和自定义序列化程序
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}
下面是我的视图类,它检索要序列化的对象
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)
这里是使用我的课程序列化程序的黑客组合序列化程序
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}
这给了我一个类似于老paginator给出的行为的结果
{
"previous": 1,
"next": 3,
"courses": [...],
"count": 384
}
我希望这有帮助。我仍然认为有一种更好的方法可以使用新的API来实现这一点,但它只是没有很好的文档记录。如果我想得更多,我会编辑我的帖子
编辑
我想我已经找到了一种更好、更优雅的方法,除了创建自己的定制分页器,以获得与旧分页序列化器类类似的行为
这是一个自定义分页器类。我重载了response和next page方法以获得我想要的结果(即?page=2
,而不是完整的url)
然后,我的课程视图与您实现它的方式非常相似,只是这次使用了自定义分页器
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": []
}
我仍然不确定这对于可浏览的API是如何工作的(我不使用drf的这个特性)。我认为您也可以为此创建自己的自定义类。我希望这有帮助 我想我已经明白了(至少在大部分情况下):
我们从一开始就应该使用的是:
只需使用内置分页器并将views.py
更改为:
from rest_framework.pagination import PageNumberPagination
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 = PageNumberPagination()
# From the docs:
# The paginate_queryset method is passed the initial queryset
# and should return an iterable object that contains only the
# data in the requested page.
result_page = paginator.paginate_queryset(courses, request)
# Now we just have to serialize the data just like you suggested.
serializer = CourseSerializer(result_page, many=True)
# From the docs:
# The get_paginated_response method is passed the serialized page
# data and should return a Response instance.
return paginator.get_paginated_response(serializer.data)
对于所需的页面大小,只需在设置.py
中设置页面大小:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 15
}
您现在应该已经完全设置好响应主体中的所有选项(count、next和back链接),就像更新之前一样
然而,还有一件事仍然困扰着我:我们也应该能够得到新的,因为某些原因,目前还缺少
我当然可以在这方面多提几点建议……我意识到这篇文章发表已经一年多了,但希望这能帮助其他人。对我类似问题的回答是我的解决方案。我使用的是DRF 3.2.3
看到它是如何实现的,我找到了在可见API中获得分页+控件所需的解决方案
我刚刚遇到了完全相同的问题。我决定升级我所有的软件包,这是唯一一个坏掉的东西。我希望这个问题能得到回答,因为我也没有发现任何东西。“我刚刚更新到Django Rest Framework 3.1,似乎一切都乱套了。”哈哈,是的。你的解决方案有效。它还不是最优的,因为我们无法在可浏览的API上获得分页链接(分页超链接也消失了),但目前它是唯一有效的。我们现在应该很接近了。如果你有更好的建议,请告诉我,否则我会在几天后接受你的回答。再次感谢。这也是正确的。我们现在几乎可以做任何事了。。!我相信解决方案的关键在于如何用一个简单的构造函数替换class Meta:object\u serializer\u class=CourseSerializer
。超过这一点,我们可以让我们的想象力接管。不管怎样,我更愿意坚持默认值,但既然你给了我“钥匙”,我就接受你的答案。谢谢,哇。真的那么简单吗?他们应该用一个例子来更新文档。至于HTML链接,我不知道,我从来没有真正使用过可浏览的API.cool!这个解决方案节省了我很多时间来检查他们的源代码。我希望他们尽快制作文档。@hauding:制作您希望在世界上看到的文档!它是开源的,文档是一种很好的回馈方式。我检查了一下,光标分页的效果也一样。事实上,DRFv3.x分页是一个巨大的改进,可以直接使用。只是用法没有记录在案。因为我找不到HTML分页控件,所以找到了这个答案。如果覆盖它,则需要在paginate\u queryset中设置self.display\u page\u controls=True
。