Pagination - potatoscript/django GitHub Wiki

📚 Pagination – Breaking Big Lists into Pages

When your application has large datasets, returning all the data at once can overwhelm both your server and users. Pagination allows you to break up a large list of items into smaller, more manageable chunks, or pages. This is a critical feature in any web application, especially when you’re working with a list of items that might grow into the thousands.

In this tutorial, we’ll explore how to implement pagination in your Django REST API using Django REST Framework (DRF).


🧩 Step 1: Why Pagination is Important

Imagine you have an API that returns a list of 1000 books from a database. If you were to request all those books at once, the response could be too large, slow to load, and might even cause performance issues.

Pagination helps by:

  • Reducing load time for users.
  • Optimizing server performance, as it only sends a portion of the data.
  • Improving user experience by allowing users to easily navigate between different chunks of data.

🧩 Step 2: How to Enable Pagination in DRF

Django REST Framework comes with several ways to paginate your API responses. We'll cover simple pagination and page size settings.

🛠️ Step 2.1: Enable Pagination Globally

To enable pagination in Django REST Framework, you need to configure the pagination settings in the settings.py file of your Django project.

  1. Open your settings.py file.
  2. Add the following pagination settings to the REST_FRAMEWORK dictionary:
# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,  # This is the number of items per page
}

Explanation:

  • DEFAULT_PAGINATION_CLASS: Specifies the pagination style. PageNumberPagination is one of the available options, which allows clients to request specific pages.
  • PAGE_SIZE: Specifies the number of items per page. Here, we've set it to 10, but you can adjust it based on your needs.

This setting will apply pagination to all of your API views that return large datasets.


🧩 Step 3: Customizing Pagination

If you want more control over how your pagination works, Django REST Framework allows you to create custom pagination classes. This can be useful if you need to customize things like the page size or the pagination style.

🛠️ Step 3.1: Custom Pagination Class

You can create a custom pagination class by subclassing one of DRF's built-in pagination classes. For instance, you might want to change how the response is formatted or adjust how the pages are numbered.

Here's an example of a custom pagination class:

# pagination.py
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class CustomPagination(PageNumberPagination):
    page_size = 5  # Items per page
    page_size_query_param = 'page_size'  # Allow clients to pass a custom page size
    max_page_size = 100  # Limit the maximum number of items per page

    def get_paginated_response(self, data):
        return Response({
            'count': self.page.paginator.count,
            'next': self.get_next_link(),
            'previous': self.get_previous_link(),
            'results': data,
        })

Explanation:

  • page_size: Set the default number of items per page.
  • page_size_query_param: Allow the client to change the page size by passing a query parameter like ?page_size=20.
  • max_page_size: Limit the maximum number of items returned per page (even if the client requests a larger page size).
  • get_paginated_response: Customize how the paginated response is returned.

Now, let’s tell DRF to use this custom pagination class in your settings.py file:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'myapp.pagination.CustomPagination',  # Custom pagination class
    'PAGE_SIZE': 10,
}

🧩 Step 4: Adding Pagination to Your Views

Once pagination is enabled, you need to ensure your API views are set up to handle it. DRF handles this automatically for most cases, but let’s see how it works with your Book API from the previous examples.

🛠️ Step 4.1: Apply Pagination to a View

Assuming you have a list view for your Book model, you can simply use pagination by modifying the view:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .models import Book
from .serializers import BookSerializer

class BookList(APIView):
    def get(self, request):
        books = Book.objects.all()  # Retrieve all books
        paginator = PageNumberPagination()  # Create a paginator instance
        result_page = paginator.paginate_queryset(books, request)  # Paginate the queryset
        serializer = BookSerializer(result_page, many=True)  # Serialize the paginated data
        return paginator.get_paginated_response(serializer.data)  # Return paginated response

In this view:

  • The PageNumberPagination() object automatically handles pagination of the books queryset.
  • The paginate_queryset() method paginates the data based on the page number provided by the client.
  • The get_paginated_response() method formats the response to include pagination metadata like the count, next, and previous links.

🧩 Step 5: Testing Pagination

You can now test pagination by visiting your API endpoint (e.g., http://127.0.0.1:8000/books/).

  1. GET Request: When you make a GET request to /books/, the response will contain the first page of books with pagination metadata:
{
    "count": 50,
    "next": "http://127.0.0.1:8000/books/?page=2",
    "previous": null,
    "results": [
        {
            "id": 1,
            "title": "Django for Beginners",
            "author": "John Doe",
            "published_date": "2020-01-01"
        },
        {
            "id": 2,
            "title": "Advanced Django",
            "author": "Jane Smith",
            "published_date": "2021-01-01"
        }
    ]
}

This response tells you:

  • The total number of books (count).
  • The URL to the next page (next).
  • The URL to the previous page (previous).
  • The list of books for the current page (results).
  1. Navigate to the Next Page: To get the next page of results, use the URL provided in the next field (?page=2).

🧩 Step 6: Handling Custom Query Parameters

You can further customize how pagination works by allowing the client to pass in custom query parameters.

🛠️ Step 6.1: Custom Page Size

As mentioned before, you can let the client specify the page size by passing a page_size parameter in the query string:

GET /books/?page=2&page_size=20

This request will return the second page with 20 books per page.


🧩 Step 7: Summary of Pagination Features

Feature Explanation
PageNumberPagination A simple way to paginate large sets of data using page numbers.
Custom Pagination Class Allows you to create a custom pagination style by subclassing DRF's built-in classes.
page_size The number of items returned per page.
next & previous Links to the next and previous pages, allowing clients to easily navigate.
Custom Page Size Clients can specify a custom page size by passing a page_size query parameter.
Pagination Metadata The paginated response includes metadata like count, next, and previous.