[Solved]-Django-Rest-Framework: Paginate nested object

14👍

Since PaginationSerializer was removed in DRF 3.1, you have to implement your own logic, for further details refer to :
https://stackoverflow.com/a/31500287/7469841

So you have to change your BookSerializer to include the pagination behaviour as following :

BookSerializer

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

Firstly You have to use the Paginator found in django.core.paginator to paginate an iterable object:

paginator = Paginator(obj.wordinbook_set.all(), page_size)

Then get the target page from paginated data :

words_in_book = paginator.page(page)

Serialize the paginated set with many=True:

serializer = WordInBookSerializer(words_in_book, many=True)

Also to make the page size dynamic you can use query_params to receive the desired page size, for example you can choose the page size to be 10 in a request and be 100 in a different request, to retrieve the page size:

page_size = self.context['request'].query_params.get('size') or 10

And finally to allow the user to request a certain page, use again the query_params to receive it:

page = self.context['request'].query_params.get('page') or 1

2👍

Hmm, believe that you should tackle it little bit differently.

First – define the @detail_route on the BooksViewSet – lets say word-in-book:

@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)

In this way you will get the additional endpoint:

/books/1/word-in-book/ which will return you the paginated results of word in books models.

Hope this helps.

I believe that pagination in your case is not possible – you can just transform code a little to return lets say: 10 first objects.

Leave a comment