Django REST Framework Pagination

Summary: in this tutorial, you will learn how to use the Django REST Framework Pagination feature to divide a list of records into multiple pages.

Introduction to Django REST Framework pagination

Suppose you have thousands of records and want to show them to users. But the screen is quite limited. Therefore, you often need to break these records into pages, each containing 5 or 10 records.

The pagination feature allows you to utilize the server resources more efficiently, improve the loading times, and enhance user experiences.

Django REST Framework pagination allows you to split a large result set into individual pages with some simple settings.

We’ll continue with the Todo API project from the previous tutorial. Let’s add some todos to the project to test out the pagination:

Django Pagination styles

Django provides different styles to paginate data. Let’s explore them.

Page number pagination

The page number pagination style accepts a single page number in the request query parameters. You can jump to specific pages easily.

To configure page number pagination, you add it to the REST_FRAMEWORK in the settings.py of the project.

For example, the following instructs the DRF to use the PageNumberPagination style with a page size of 2:

REST_FRAMEWORK = {
    # ...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}Code language: Python (python)

Once the setup is in place, you can make a GET request to the endpoint /api/v1/todos?page=2 in the web browser.

Here’s the response:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 6,
    "next": "http://localhost:8000/api/v1/todos/?page=3",
    "previous": "http://localhost:8000/api/v1/todos/",
    "results": [
        {
            "id": 3,
            "title": "Master Django REST API",
            "completed": false,
            "user": "john"
        },
        {
            "id": 6,
            "title": "Deploy API to Server",
            "completed": false,
            "user": "john"
        }
    ]
}Code language: Python (python)

In the response:

  • count specifies the total records.
  • next & previous denote the links to the next and previous page.
  • results store the records specified by the PAGE_SIZE. In this example, each page contains 2 records.

Limit Offset Pagination

The limit offset pagination simulates the way to search for multiple records in a database. The client tells the server two things:

  • The maximum number of records to return per page (limit).
  • Where the list begins among the records. (offset)

If you are familiar with MySQL or PostgreSQL, the limit offset pagination works like the LIMIT and OFFSET clauses.

The following shows how to configure the limit offset pagination in the settings.py of the project:

REST_FRAMEWORK = {
     # ...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 2
}Code language: Python (python)

If you make a GET request to the endpoint /api/v1/todos/?limit=2&offset=2, you’ll get the following response:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 6,
    "next": "http://localhost:8000/api/v1/todos/?limit=2&offset=4",
    "previous": "http://localhost:8000/api/v1/todos/?limit=2",
    "results": [
        {
            "id": 3,
            "title": "Master Django REST API",
            "completed": false,
            "user": "john"
        },
        {
            "id": 6,
            "title": "Deploy API to Server",
            "completed": false,
            "user": "john"
        }
    ]
}Code language: Python (python)

The LimitOffsetPagination style works like the PageNumberPagination style except that it uses two query string parameters limit and offset.

Cursor Pagination

The limitation of the offset-based including PageNumberPagination and LimitOffsetPagination is that they are not efficient for extremely large datasets.

This is where the cursor pagination comes to the rescue. The cursor pagination works efficiently for large datasets.

The cursor pagination uses an opaque “cursor” indicator for paging. It offers forward and reverse controls for navigation.

The cursor pagination requires a consistent and unique order in the result set. It also doesn’t allow jumping to an arbitrary position in the data set.

The following shows the settings of the CursorPagination in the settings.py file:

REST_FRAMEWORK = {
    # ...
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
    'PAGE_SIZE': 2
}Code language: Python (python)

By default, the CursorPagination assumes that the model has the “created” timestamp field. It’ll return the most recently created records first because the default order is "-created".

If the model doesn’t have the “created” field, you need to specify another field such as id. To do that, you follow these steps:

First, define a subclass of the CursorPagination class:

class TodoCursorPagination(CursorPagination):
    ordering = 'id'  # Default ordering
    page_size = 2   # Set your desired page sizeCode language: Python (python)

Second, use the TodoCursorPagination in the view:

class TodoList(generics.ListCreateAPIView):
    pagination_class = TodoCursorPagination
    # ...Code language: Python (python)

This example shows how to configure the pagination style at the view level. Unlike the global setting, the setting at the view level is only applied to a specific view.

If you make a GET request to the API endpoint /api/v1/todos/, you’ll get the following response:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "next": "http://localhost:8000/api/v1/todos/?cursor=cD0y",
    "previous": null,
    "results": [
        {
            "id": 1,
            "title": "Learn Python",
            "completed": false,
            "user": "john"
        },
        {
            "id": 2,
            "title": "Study Django",
            "completed": false,
            "user": "john"
        }
    ]
}Code language: Python (python)

Download the project source code

Click the following link to download the project source code.

Summary

  • Django REST Framework allows you to set the pagination style at the global and view levels.
  • Django REST Framework offers three pagination styles including page number pagination, limit offset pagination, and cursor pagination.
  • The CursorPagination works very efficiently with extremely large datasets.
Did you find this tutorial helpful ?