""" Pagination serializers determine the structure of the output that should be used for paginated responses. """ from __future__ import unicode_literals from rest_framework import serializers from rest_framework.templatetags.rest_framework import replace_query_param class NextPageField(serializers.Field): """ Field that returns a link to the next page in paginated results. """ page_field = 'page' def to_representation(self, value): if not value.has_next(): return None page = value.next_page_number() request = self.context.get('request') url = request and request.build_absolute_uri() or '' return replace_query_param(url, self.page_field, page) class PreviousPageField(serializers.Field): """ Field that returns a link to the previous page in paginated results. """ page_field = 'page' def to_representation(self, value): if not value.has_previous(): return None page = value.previous_page_number() request = self.context.get('request') url = request and request.build_absolute_uri() or '' return replace_query_param(url, self.page_field, page) class DefaultObjectSerializer(serializers.ReadOnlyField): """ If no object serializer is specified, then this serializer will be applied as the default. """ def __init__(self, source=None, many=None, context=None): # Note: Swallow context and many kwargs - only required for # eg. ModelSerializer. super(DefaultObjectSerializer, self).__init__(source=source) class BasePaginationSerializer(serializers.Serializer): """ A base class for pagination serializers to inherit from, to make implementing custom serializers more easy. """ results_field = 'results' def __init__(self, *args, **kwargs): """ Override init to add in the object serializer field on-the-fly. """ super(BasePaginationSerializer, self).__init__(*args, **kwargs) results_field = self.results_field try: object_serializer = self.Meta.object_serializer_class except AttributeError: object_serializer = DefaultObjectSerializer self.fields[results_field] = serializers.ListSerializer( child=object_serializer(), source='object_list' ) self.fields[results_field].bind(results_field, self, self) class PaginationSerializer(BasePaginationSerializer): """ A default implementation of a pagination serializer. """ count = serializers.ReadOnlyField(source='paginator.count') next = NextPageField(source='*') previous = PreviousPageField(source='*')