pagination

Learn how to implement pagination in Django REST Framework for efficient API data handling. Covers generic views, viewsets, and APIView with code examples.

Django REST Framework Pagination

Implementing Pagination in Django REST Framework

Pagination is a crucial technique for managing large datasets in APIs, preventing performance issues and improving user experience. Django REST Framework (DRF) provides robust tools to implement pagination easily. This guide explains how to apply pagination effectively, whether you are using generic class-based views, viewsets, or custom APIView.

Pagination with Generic Class-based Views and Viewsets

For generic class-based views and viewsets, DRF can automatically handle pagination. To enable this, you primarily need to configure your settings.py file by overriding the DEFAULT_PAGINATION_CLASS and PAGE_SIZE settings.

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 20
}

This configuration sets LimitOffsetPagination as the default pagination class, with each page containing 20 items. You can choose other pagination classes like PageNumberPagination based on your needs.

Pagination with APIView or Non-Generic Views

When using APIView or other non-generic views, pagination must be explicitly applied within the view itself. First, define the default pagination behavior in settings.py as shown above.

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 20
}

Next, you need to integrate pagination logic into your APIView. This involves setting the pagination_class attribute and overriding the get method to use the paginator.

from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rest_framework.response import Response

class PostView(APIView):
    # Assume queryset and serializer_class are defined elsewhere
    # queryset = ...
    # serializer_class = ...

    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get(self, request):
        # Apply pagination to the queryset
        page = self.paginate_queryset(self.queryset)
        if page is not None:
            serializer = self.serializer_class(page, many=True)
            return self.get_paginated_response(serializer.data)
        
        # If pagination is disabled or not applicable
        serializer = self.serializer_class(self.queryset, many=True)
        return Response(serializer.data)

    # Helper methods for pagination, typically found in generic views
    @property
    def paginator(self):
        """The paginator instance associated with the view, or `None`."""
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        """Return a single page of results, or `None` if pagination is disabled."""
        if self.paginator is None:
            return None
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

    def get_paginated_response(self, data):
        """Return a paginated style `Response` object for the given output data."""
        return self.paginator.get_paginated_response(data)

Customizing Pagination Classes

DRF allows you to create custom pagination classes to tailor pagination behavior. By extending existing pagination classes (like PageNumberPagination), you can override default attributes such as page_size, page_size_query_param, and max_page_size.

from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
    """
    Client controls the response page size (with query param), limited to a maximum of `max_page_size` and default of `page_size`.
    """
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 10000

You can then assign this CustomPagination class to specific views or set it as the default in settings.py.

Back to Top ↑