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 thePAGE_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 size
Code 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.