首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django-Rest-Framework:分页嵌套对象

Django-Rest-Framework:分页嵌套对象
EN

Stack Overflow用户
提问于 2016-11-25 22:10:50
回答 2查看 3.4K关注 0票数 8

我有两个模型:

代码语言:javascript
复制
class Book(models.Model):
    title = models.CharField(max_length=250)
    author = models.CharField(max_length=250)
class WordInBook(models.Model):
    book = models.ForeignKey("Book")
    word = models.ForeignKey("Word")

和相应的串行化器:

代码语言:javascript
复制
class BookSerializer(ModelSerializer):
    wordinbook_set = WordInBookSerializer(many=True)

    class Meta:
        model = Book
        fields = ('id', 'title', 'author', 'wordinbook_set')

class WordInBookSerializer(ModelSerializer):
    class Meta:
        model = WordInBook
        fields = ('word')

现在,我想对wordinbook_set进行分页。在序列化程序之外,这很容易:

代码语言:javascript
复制
book = Book.objects.get(pk=book_id)
paginator = Paginator(book.wordinbook_set.all(), 10)
words = paginator.page(page).object_list

但这就给我留下了两个独立的序列化对象。

问:如何在序列化程序中对wordinbook_set进行分页?

生成的json应该如下所示:

代码语言:javascript
复制
{id: '...', title: '...', author: '...', wordinbook_set: [ 10 WordInBook objects here ]}
EN

回答 2

Stack Overflow用户

发布于 2018-04-06 01:13:45

由于DRF3.1中删除了PaginationSerializer,因此您必须实现自己的逻辑,有关更多详细信息,请参阅:https://stackoverflow.com/a/31500287/7469841

因此,您必须更改BookSerializer以包含分页行为,如下所示:

BookSerializer

代码语言:javascript
复制
class BookSerializer(ModelSerializer):
        wordinbook_set = serializers.SerializerMethodField('paginated_wordinbook')

        class Meta:
            model = Book
            fields = ('id', 'title', 'author', 'wordinbook_set')

        def paginated_wordinbook(self, obj):
            page_size = self.context['request'].query_params.get('size') or 10
            paginator = Paginator(obj.wordinbook_set.all(), page_size)
            page = self.context['request'].query_params.get('page') or 1

            words_in_book = paginator.page(page)
            serializer = WordInBookSerializer(words_in_book, many=True)

            return serializer.data

首先,您必须使用django.core.paginator中的分页器对可迭代对象进行分页:

代码语言:javascript
复制
paginator = Paginator(obj.wordinbook_set.all(), page_size)

然后从分页数据中获取目标页面:

代码语言:javascript
复制
words_in_book = paginator.page(page)

使用many=True序列化分页集

代码语言:javascript
复制
serializer = WordInBookSerializer(words_in_book, many=True)

此外,要使页面大小动态,您可以使用query_params接收所需的页面大小,例如,您可以在请求中选择页面大小为10,在不同的请求中选择为100,以检索页面大小:

代码语言:javascript
复制
page_size = self.context['request'].query_params.get('size') or 10

最后,为了允许用户请求某个页面,再次使用query_params接收该页面:

代码语言:javascript
复制
page = self.context['request'].query_params.get('page') or 1
票数 9
EN

Stack Overflow用户

发布于 2017-04-19 21:21:20

嗯,相信你应该以不同的方式来处理它。

首先-在BooksViewSet上定义@detail_route -比方说word-in-book:

代码语言:javascript
复制
@detail_route(method=['GET'], url_path='word-in-book')
def word_in_book(self, request, *args, **kwargs):
    object = self.get_object()
    queryset = object.wordinbook_set.all()

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = WordInBookSerializer(page, many=True)
        return self.get_paginated_response(serializer.data)

    serializer = self.get_serializer(queryset, many=True)
    return Response(serializer.data)

这样,您将获得额外的端点:

/books/1/word-in-book/,它将返回word在书籍模型中的分页结果。

希望这能有所帮助。

我认为在你的例子中分页是不可能的-你可以稍微转换一下代码来返回,比如说: 10个第一个对象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40806879

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档