I am using the Django REST Framework and I need to paginate a list based on a GET parameter provided with the request.
I know that I can set 'PAGINATE_BY': 10
in the settings, however I want to allow the caller to specify the number they want to paginate by when making the request.
I currently have the following serializer:
from api.models import Countries
from rest_framework import serializers
class CountrySerializer(serializers.Serializer):
country_geoname_id = serializers.CharField(required=True)
country_code = serializers.CharField(source="iso", max_length=2L, required=True)
country_name = serializers.CharField(max_length=64L, required=True)
def transform_iso(self, obj, value):
return "country_code"
And I have tried the following view:
@api_view(['GET'])
def country_list(request):
"""
List all countries
"""
if request.method == 'GET':
queryset = Countries.objects.all()
serializer = CountrySerializer(queryset, many=True, data=request.DATA)
paginate_by = request.GET.get('limit', 10)
return Response(serializer.data)
However I feel I am missing something, and I have been unable to figure it out from the documentation.
Should I be doing the pagination in the serializer or in the view?
Thanks in advance.
Let's break the problem down:
You need to create a pagination method that allows the user to define the page size:
As stated in the PageNumberPagination
in the DRF documentation, you can define a parameter name by overriding the page_size_query_param
:
If set, this is a string value indicating the name of a query parameter that allows the client to set the page size on a per-request basis. Defaults to
None
, indicating that the client may not control the requested page size.
You can achieve that by one of the following ways:
In settings.py
add the following:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'PAGINATE_BY_PARAM': 'page_size'
}
Or you can create a custom pagination class and override your settings there:
from rest_framework.pagination import PageNumberPagination
class MyPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
Finally you need to define which pagination class you will use in your view function.
The following example will work for either of the aforementioned cases by just changing the value of the paginator
variable to PageNumberPaginator
or MyPaginator
:
from rest_framework.pagination import PageNumberPagination
@api_view(['GET'])
def country_list(request):
"""
List all countries
"""
if request.method == 'GET':
paginator = PageNumberPagination()
queryset = Countries.objects.all()
context = paginator.paginate_queryset(queryset, request)
serializer = CountrySerializer(context, many=True)
return paginator.get_paginated_response(serializer.data)
Now you have function based view with pagination and a query parameter to change the page size.
Try the PAGINATE_BY_PARAM
setting. This snippet should get you pretty close:
class CountryListView(ListAPIView):
model = Countries
serializer_class = CountrySerializer
paginate_by_param = 'limit'
See http://www.django-rest-framework.org/api-guide/pagination#pagination-in-the-generic-views
My snippet uses generic views to take a lot of the repetition out, I recommend giving those a look, too. http://www.django-rest-framework.org/api-guide/generic-views
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With