Django Rest框架3.1打破了分页.PaginationSerializer [英] Django Rest Framework 3.1 breaks pagination.PaginationSerializer
问题描述
我刚刚更新到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
这是正常工作。现在随着3.1的发布,我找不到如何做同样的事情,因为 PaginationSerializer
不再存在。
我试图子类 PageNumberPagination
并使用其默认的 paginate_queryset
和 get_paginated_response
方法,但我无法再将其结果序列化。
换句话说,我的问题是我不能再这样做:
class Meta:
object_serializer_class = TaskSerializer
任何想法?
提前感谢
我不知道这是否是完全正确的方法这样做,但它适合我的需要。它使用Django Paginator和一个自定义的序列化程序。
这是我的View类,用于检索序列化对象
class CourseListView(AuthView):
def get(self,request,format = None):
返回带有列表的JSON响应当然对象
courses = Course.objects.order_by('name')。all()
serializer = PaginatedCourseSerializer(课程,请求,25)
返回响应(serializer.data)
这是使用我的课程序列化程序的黑客入门Serializer。
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.pag
除了PageNotAnInteger:
courses = paginator.page(1)
除了EmptyPage:
courses = paginator.page(paginator.num_pages)
count = paginator.count
以前= None如果不是courses.has_previous()else courses.previous_page_number()
next =无如果不是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)。
pre $
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响应({'count':self.page.paginator.count,
'next':self.get_next_link(),
'previous ':self.get_previous_link(),
'courses':data})
def get_next_link(self):
如果不是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):
如果不是self.page.has_previous():
r eturn无
page_number = self.page.previous_page_number()
return replace_query_param('',self.page_query_param,page_number)
然后我的课程视图与实现它的方式非常相似,只有这一次使用自定义分页符。
code> class CourseListView(AuthView):
def get(self,request,format = None):
返回带有课程对象列表的JSON响应
courses = Course.objects.order_by('name')。all()
paginator = CustomCoursePaginator()
result_page = paginator.paginate_queryset(courses,request)
serializer = CourseSerializer(result_page,many = True)
返回paginator.get_paginated_response(serializer.data)
现在我得到我正在寻找的结果。
{
count:384 ,
next:?page = 3,
pre v $:?page = 1,
courses:[]
}
我仍然不确定这是否适用于Browsable API(我没有使用drf的这个功能)。我想你也可以为此创建自己的自定义类。我希望这有帮助!
I just updated to Django Rest Framework 3.1 and it seems that all hell broke loose.
in my serializers.py
I was having the following code:
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = task
exclude = ('key', ...)
class PaginatedTaskSerializer(pagination.PaginationSerializer):
class Meta:
object_serializer_class = TaskSerializer
which was working just fine. Now with the release of 3.1 I can't find examples on how to do the same thing since PaginationSerializer
is no longer there.
I have tried to subclass PageNumberPagination
and use its default paginate_queryset
and get_paginated_response
methods but I can no longer get their results serialized.
In other words my problem is that I can no longer do this:
class Meta:
object_serializer_class = TaskSerializer
Any ideas?
Thanks in advance
I am not sure if this is the completely correct way to do it, but it works for my needs. It uses the Django Paginator and a custom serializer.
Here is my View Class that retrieves the objects for serialization
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)
Here is the hacked together Serializer that uses my Course serializer.
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}
This gives me a result that is similar to the behavior that the old paginator gave.
{
"previous": 1,
"next": 3,
"courses": [...],
"count": 384
}
I hope this helps. I still think there has got to be a beter way to do this wiht the new API, but it's just not documented well. If I figure anything more out, I'll edit my post.
EDIT
I think I have found a better, more elegant way to do it bey creating my own custom paginator to get behavior like I used to get with the old Paginated Serializer class.
This is a custom paginator class. I overloaded the response and next page methods to get the result I want (i.e. ?page=2
instead of the full 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)
Then my course view is very similar to how you implemented it, only this time using the 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)
Now I get the result that I'm looking for.
{
"count": 384,
"next": "?page=3",
"previous": "?page=1",
"courses": []
}
I am still not certain about how this works for the Browsable API (I don't user this feature of drf). I think you can also create your own custom class for this. I hope this helps!
这篇关于Django Rest框架3.1打破了分页.PaginationSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!