[Django]-Django Rest Framework Pagination Settings – Content-Range

7πŸ‘

βœ…

1. Including Link Header in response:

To include a Link header in your response, you need to create a custom pagination serializer class, This should subclass pagination.BasePagination and override the get_paginated_response(self, data) method.

Example (taken from docs):

Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links in a Link header, we override the get_paginated_response() .

class LinkHeaderPagination(pagination.PageNumberPagination):

    def get_paginated_response(self, data):
        next_url = self.get_next_link()
        previous_url = self.get_previous_link()

        if next_url is not None and previous_url is not None:
            link = '<{next_url}; rel="next">, <{previous_url}; rel="prev">'
        elif next_url is not None:
            link = '<{next_url}; rel="next">'
        elif previous_url is not None:
            link = '<{previous_url}; rel="prev">'
        else:
            link = ''

        link = link.format(next_url=next_url, previous_url=previous_url)
        headers = {'Link': link} if link else {}

        return Response(data, headers=headers)

After this, we need to include this pagination class in our settings so that it is used by DRF instead of the default pagination classes.

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.LinkHeaderPagination',
    'PAGE_SIZE': 100
}

API responses for list endpoints will now include a Link header.

pag

2. Including Content-Range Header in response:

You can also send Content-Range header instead of Link. Just create a headers dictionary with Content-Range as the key and value as how many items are being returned and how many total items exist.

For example:

class ContentRangeHeaderPagination(pagination.PageNumberPagination):

    def get_paginated_response(self, data):
        total_items = self.page.paginator.count
        item_starting_index = self.page.start_index() - 1 # In a page, indexing starts from 1
        item_ending_index = self.page.end_index() - 1

        content_range = 'items {0}-{1}/{2}'.format(item_starting_index, item_ending_index, total_items)      

        headers = {'Content-Range': content_range} 

        return Response(data, headers=headers)

Suppose this is the header received:

Content-Range: items 0-9/50 

This tells us that the response has a Content-Range header with value as items 0-9/50. This indicates that first 10 items are returned out of total 50.

You can also use * instead of total no. of items if calculating total is expensive.

Content-Range: items 0-9/* # Use this if total is expensive to calculate
πŸ‘€Rahul Gupta

0πŸ‘

DRF recommends a thirdparty package in its documentation: django-rest-framework-link-header-pagination

It is supposed to follow the same path as the Github API, which is basically the proper way of doing what the other answer suggest.

Here is a sample Link header taken from Github’s API guide:

Link: <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15>; rel="next",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=1>; rel="first",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=13>; rel="prev"

I haven’t tried the package yet but I’ll report back once done.

πŸ‘€DarkFranX

Leave a comment