Implementing Pagination in Django REST Framework
Django REST Framework provides three built-in pagination classes that can be used to paginate API responses. Each pagination type serves different use cases depending on your application's requirements.
PageNumberPagination
This is the most commonly used pagination style, displaying results by page number with configurable page size.
Serializers
from rest_framework import serializers
from api import models
class PagerSerialiser(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = "__all__"
View Implementation
from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
roles = models.Role.objects.all()
pg = PageNumberPagination()
page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
ser = PagerSerialiser(instance=page_roles, many=True)
return Response(ser.data)
Configuration
REST_FRAMEWORK = {
"PAGE_SIZE": 2
}
URL Routing
urlpatterns = [
url(r'(?P<version>[v1|v2]+)/page1/', Pager1View.as_view()),
]
Access the second page via ?page=2 query parameter.
Customizing PageNumberPagination
You can subclass PageNumberPagination to customize its behavior:
class MyPageNumberPagination(PageNumberPagination):
page_size = 3
page_size_query_param = "size"
max_page_size = 10
page_query_param = "page"
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
roles = models.Role.objects.all()
pg = MyPageNumberPagination()
page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
ser = PagerSerialiser(instance=page_roles, many=True)
return Response(ser.data)
LimitOffsetPagination
This pagination style allows specifying a starting offset and the number of items to return from that position.
class MyLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2
offset_query_param = "offset"
limit_query_param = "limit"
max_limit = 10
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
roles = models.Role.objects.all()
pg = MyLimitOffsetPagination()
page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
ser = PagerSerialiser(instance=page_roles, many=True)
return Response(ser.data)
To retrieve 1 item starting from the 3rd record:
http://127.0.0.1:8000/api/v1/pager1/?offset=3&limit=1
Using get_paginated_response method automatically includes previous and next page links in the resposne.
CursorPagination
Cursor-based paginasion is designed for large datasets where traditional offfset-based pagination degrades in performance. Instead of using page numbers, it maintains the minimum and maximum ID values internally to optimize query performance. This approach prevents users from jumping directly to arbitrary pages (e.g., jumping from page 1 to page 100) which can cause performance issues with large datasets.
This pagination style only allows navigation through previous and next links.
class MyCursorPagination(CursorPagination):
cursor_query_param = "cursor"
page_size = 2
ordering = 'id'
page_size_query_param = None
max_page_size = None
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
roles = models.Role.objects.all()
pg = MyCursorPagination()
page_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
ser = PagerSerialiser(instance=page_roles, many=True)
return pg.get_paginated_response(ser.data)
Summary
| Pagination Type | Use Case | Key Parameters |
|---|---|---|
| PageNumberPagination | Standard page-based navigation | page, size |
| LimitOffsetPagination | Offset-based data retrieval | offset, limit |
| CursorPagination | Large datasets, secure navigation | cursor |