Django Rest Framework Pagination
While digging into some React recently, I had to integrate with an API I have running using DRF. I was using the default pagination and found that a few things were missing that would make it much easier for the front end to consume the API results.
from rest_framework import pagination
from rest_framework.response import Response
import math
class CustomPagination(pagination.PageNumberPagination):
page_size_query_param = 'page_size'
max_page_size = 100
def get_paginated_response(self, data):
return Response({
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'total': self.page.paginator.count,
'page_size': self.get_page_size(self.request),
'page_total': len(data),
'max_page_size': self.max_page_size,
'num_of_pages': math.ceil(self.page.paginator.count / self.get_page_size(self.request)),
'results': data
})
With the default pagination we get the following:
{
"count": 48,
"next": null,
"previous": "https://serviceurl/api/customers?page=4",
"results" : [...]
}
Now with the custom class we get a few helpers:
{
"next": "https://serviceurl/api/customers/?page=2",
"previous": null,
"total": 48,
"page_size": 10,
"page_total": 10,
"max_page_size": 100,
"num_of_pages": 5,
"results": [...]
}
You might ask why include the page_size? We have the number of pages so we can just create a promise and pull all of the pages at the same time. True, but if you want to change the page_size parameter, then the number of pages will change - calling https://serviceurl/api/customers/?page_size=100
for example:
{
"next": null,
"previous": null,
"total": 48,
"page_size": 100,
"page_total": 48,
"max_page_size": 100,
"num_of_pages": 1,
"results": [...]
}
I think it’s best to have the server side calculate this for you (as it’s already doing it). The frontend shouldn’t need to recreate the wheel here.