Skip to content

Django REST Pagination Custom Fix

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Django REST Pagination Custom Fix. We cover key concepts, practical examples, and best practices.

The Problem

DRF's default PageNumberPagination works but the response format, page size, and query params may not match your frontend or API contract requirements.

Quick Fix

Wrong — relying on defaults

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}

Output: Page size is hardcoded. Response includes count, next, previous, results. Clients can't customize page size.

Correct — custom pagination class

from rest_framework.pagination import PageNumberPagination

class StandardPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100
    page_query_param = 'p'

class ProductViewSet(viewsets.ModelViewSet):
    pagination_class = StandardPagination

Output: GET /products/?p=2&page_size=50 returns up to 50 items per page, capped at 100.

Cursor pagination for real-time data

from rest_framework.pagination import CursorPagination

class OrderPagination(CursorPagination):
    page_size = 20
    ordering = '-created_at'
    cursor_query_param = 'c'

Output: Stable cursor-based pagination. New items inserted at the top don't cause duplicates.

Custom response format

class CustomPagination(PageNumberPagination):
    page_size = 20

    def get_paginated_response(self, data):
        return Response({
            'total': self.page.paginator.count,
            'page': self.page.number,
            'pages': self.page.paginator.num_pages,
            'items': data,
        })

Prevention

  • Create a project-level pagination class in a shared module.
  • Set it as DEFAULT_PAGINATION_CLASS in settings.
  • Override pagination_class per view only when you need different behavior.

Common Mistakes with rest pagination custom

  1. Using return to exit a function early instead of wrapping a pure value in the monad
  2. Mixing let bindings with <- bindings in do notation, producing type errors
  3. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors

These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What's the difference between PageNumber and Cursor pagination?

PageNumber pagination uses ?page=2. Cursor pagination uses an opaque cursor string. Cursor pagination is stable for real-time data but doesn't support jumping to arbitrary pages.

How do I disable pagination for a specific view?

Set pagination_class = None on the view.

Can clients control the page size?

Yes, if you set page_size_query_param. Always set max_page_size to prevent abuse.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro