[Fixed]-How to paginate response from function based view of django rest framework?

52👍

http://www.django-rest-framework.org/api-guide/pagination/

from rest_framework.pagination import PageNumberPagination

@api_view(['GET',])

@permission_classes([AllowAny,])

def PersonView(request):

    paginator = PageNumberPagination()
    paginator.page_size = 10
    person_objects = Person.objects.all()
    result_page = paginator.paginate_queryset(person_objects, request)
    serializer = PersonSerializer(result_page, many=True)
    return paginator.get_paginated_response(serializer.data)

6👍

You can also define custom pagination class by overriding PageNumberPagination

pagination.py

from rest_framework import pagination
class StandardResultsSetPagination(pagination.PageNumberPagination):
    page_size = 10
    page_query_param = 'page'
    page_size_query_param = 'per_page'
    max_page_size = 1000

it will help to define

page_size, page query custom parameters and max_page_size

views.py

from rest_api.pagination import StandardResultsSetPagination

@api_view(['GET',])
@permission_classes([AllowAny,])
def PersonView(request):
    person_objects = Person.objects.all()
    if len(person_objects)> 0:
        paginator = StandardResultsSetPagination()
        result_page = paginator.paginate_queryset(person_objects, request)
        serializer = PersonSerializer(result_page, many=True)
        return paginator.get_paginated_response(serializer.data)
    else:
        return Response({},status=status.HTTP_200_OK)

Eg:
Request

GET https://api.example.org/persons/?page=1&per_page=10

Response

HTTP 200 OK
{
    "count": 1023
    "next": "https://api.example.org/persons/?page=2&per_page=10",
    "previous": null,
    "results": [
       …
    ]
}
👤vijay

2👍

The ACCEPTED answer has a BUG

A ModelSerializer accepts a queryset or an object, in the accepted answer the PersonSerializer is given the ouput of paginator.paginate_queryset which returns a list containing single element of class Page and thus the serializer will either return incomplete data or no data at all(know this because have tried and seen wrong results).

This can be easily fixed by passing the actual queryset to the serializer which in this case will be person_objects,

So the final code will be,

from rest_framework.pagination import PageNumberPagination

@api_view(['GET',])
@permission_classes([AllowAny,])
def PersonView(request):
    paginator = PageNumberPagination()
    paginator.page_size = 10
    person_objects = Person.objects.all()
    result_page = paginator.paginate_queryset(person_objects, request)
    serializer = PersonSerializer(person_objects, many=True)  # MAIN CHANGE IS HERE
    return paginator.get_paginated_response(serializer.data)

This fixes the bug but passing the complete queryset to serializer will take lot of time for serializing since serializer works on lazy approach, but this performance issue is in itself a new question.

Leave a comment