kst*_*tis 17 python django pagination django-pagination django-rest-framework
我刚刚更新到Django Rest Framework 3.1,似乎一切都崩溃了.
在我的serializers.py我有以下代码:
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = task
exclude = ('key', ...)
class PaginatedTaskSerializer(pagination.PaginationSerializer):
class Meta:
object_serializer_class = TaskSerializer
Run Code Online (Sandbox Code Playgroud)
哪个工作得很好.现在随着3.1的发布,我无法找到关于如何做同样事情的例子,因为PaginationSerializer已经不存在了.我试图子类PageNumberPagination并使用它的默认paginate_queryset和get_paginated_response方法,但我不能再将它们的结果序列化.
换句话说,我的问题是我不能再这样做了:
class Meta:
object_serializer_class = TaskSerializer
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
提前致谢
kst*_*tis 22
我想我想出来了(至少大部分):
从一开始我们应该使用的是:
只需使用内置的分页器并将其更改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)
Run Code Online (Sandbox Code Playgroud)
对于所需的页面大小刚好设置PAGE_SIZE在settings.py:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 15
}
Run Code Online (Sandbox Code Playgroud)
您现在应该已经全部设置了响应正文中存在的所有选项(计数,下一个和后一个链接),就像更新之前一样.
然而还有一件事情让我感到困扰:我们也应该能够获得新的html分页控件,这些控件由于某些原因暂时缺失...
我绝对可以在这个问题上使用更多的建议......
Bro*_*bin 11
我不确定这是否是完全正确的方法,但它适合我的需要.它使用Django Paginator和自定义序列化器.
这是我的View类,它检索序列化的对象
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)
Run Code Online (Sandbox Code Playgroud)
这是使用我的课程序列化程序的黑客一起串行化程序.
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}
Run Code Online (Sandbox Code Playgroud)
这给了我一个类似于旧分页器给出的行为的结果.
{
"previous": 1,
"next": 3,
"courses": [...],
"count": 384
}
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助.我仍然认为必须采用一种更好的方式来实现新的API,但它并没有很好地记录下来.如果我想出更多的东西,我会编辑我的帖子.
我想我已经找到了一种更好,更优雅的方法来创建我自己的自定义分页器来获得像以前用旧的Paginated Serializer类那样的行为.
这是一个自定义的分页器类.我重载了响应和下一页的方法来获得我想要的结果(即?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)
Run Code Online (Sandbox Code Playgroud)
然后我的课程视图与您实现它的方式非常相似,只是这次使用Custom 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()
paginator = CustomCoursePaginator()
result_page = paginator.paginate_queryset(courses, request)
serializer = CourseSerializer(result_page, many=True)
return paginator.get_paginated_response(serializer.data)
Run Code Online (Sandbox Code Playgroud)
现在我得到了我正在寻找的结果.
{
"count": 384,
"next": "?page=3",
"previous": "?page=1",
"courses": []
}
Run Code Online (Sandbox Code Playgroud)
我仍然不确定它如何适用于Browsable API(我没有使用drf的这个功能).我想你也可以为此创建自己的自定义类.我希望这有帮助!