Django Rest Framework 3.1 中断 pagination.PaginationSerializer [英] Django Rest Framework 3.1 breaks pagination.PaginationSerializer

查看:27
本文介绍了Django Rest Framework 3.1 中断 pagination.PaginationSerializer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚更新到 Django Rest Framework 3.1,似乎一切都变得糟糕了.

I just updated to Django Rest Framework 3.1 and it seems that all hell broke loose.

在我的 serializers.py 中,我有以下代码:

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

工作得很好.现在随着 3.1 的发布,我找不到关于如何做同样事情的例子,因为 PaginationSerializer 不再存在.我尝试将 PageNumberPagination 子类化并使用其默认的 pagination_querysetget_paginated_response 方法,但我无法再将它们的结果序列化.

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

有什么想法吗?

提前致谢

推荐答案

我不确定这是否是完全正确的方法,但它可以满足我的需要.它使用 Django 分页器和自定义序列化程序.

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)

这是使用我的 Course 序列化器的 hacked 序列化器.

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
}

我希望这会有所帮助.我仍然认为必须有更好的方法来使用新的 API 来做到这一点,但只是没有很好地记录.如果我想出更多的东西,我会编辑我的帖子.

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.

我想我找到了一种更好、更优雅的方法来做到这一点,即创建我自己的自定义分页器来获得像我以前使用旧的分页序列化器类那样的行为.

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.

这是一个自定义分页器类.我重载了响应和下一页方法以获得我想要的结果(即 ?page=2 而不是完整的 url).

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": []
}

我仍然不确定这对可浏览 API 是如何工作的(我不使用 drf 的这个功能).我认为您也可以为此创建自己的自定义类.我希望这会有所帮助!

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 Framework 3.1 中断 pagination.PaginationSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆