Upgrading to Django REST Framework 3.1 Pagination

Upgrading to Django REST Framework 3.0 can be a daunting task. As with any major software release, certain parts become backwards incompatible, causing the need to sweep through all your code and rewrite logic where necessary. The following DRF version, 3.1 brought another significant change: brand new pagination functionality.

I am going to list few requirements for upgrading to DRF 3.1 style pagination, without changing your current API. I am not going to discuss in detail the new features, like the new pagination styles or ability to add custom pagination, as it goes beyond the scope of this post. I highly recommend you to check out the official docs, as they present the information regarding new features in a very nice and detailed way.

In DRF 3.1 there are now several different pagination styles – in addition to the standard Page Number Pagination, they added Limit Offset Pagination and Cursor Pagination. Since there are now several different pagination styles, each having their own attribute set, the logic controlling pagination has been moved to the newly added Pagination Classes.  As a result pagination is no longer controlled by the attributes of Generic Views like paginate_by,  page_query_param, etc. Although as for DRF 3.1.1 they still work, those attributes are currently pending deprecation. 

In order to include custom pagination attributes you need to define them in a pagination class and include this class as a pagination_class attribute in a Generic View.

Let’s assume that your current project contains List Views that mostly display 20 items per page while there are some views that display 10 items per page. In this case you would include the PageNumberPagination class in the settings module:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,
}

As you can see PAGINATE_BY parameter is now replaced with PAGE_SIZE.

In order to use different pagination other than the one defined in settings you will need to subclass the base PageNumberPagination class:

from rest_framework.pagination import PageNumberPagination

class TenItemsSetPagination(PageNumberPagination):
    page_size = 10

Other attributes include max_page_size and page_size_query_param. For the full list refer to official docs.

After you define a pagination class, you need to include it in a Generic View.

class StudentsListView(ListAPIView):
    pagination_class = TenItemsSetPagination
    # other attributes..

If you wish to have a view that has no pagination controls you can subclass PageNumberPagination and set page_size attribute to None:

class NotPaginatedSetPagination(PageNumberPagination):
    page_size = None

And that is all you need to do to upgrade to new style pagination, while maintaining your current API.

Another significant change – pagination no longer relies on serializers. The PaginationSerializer class does not exist in the new DRF. If you are using pagination in a standard APIView or a function based view, you’ll need to either convert it to the Generic API View or write a custom paginated output.

To conclude, upgrading to DRF 3.1 style pagination is pretty straightforward for Generic API View based projects. But if most of your API uses standard APIView or function based views, then it might take some additional time and effort. For a full reference and list of new features refer to official docs and also the release notes