aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/pagination.py
blob: 9c8dda8f98a06ffd0fb9f40b992cb0148100bde5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""
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.Serializer):
    """
    If no object serializer is specified, then this serializer will be applied
    as the default.
    """
    def to_representation(self, value):
        return value


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

        try:
            list_serializer_class = object_serializer.Meta.list_serializer_class
        except AttributeError:
            list_serializer_class = serializers.ListSerializer

        self.fields[results_field] = list_serializer_class(
            child=object_serializer(*args, **kwargs),
            source='object_list'
        )


class PaginationSerializer(BasePaginationSerializer):
    """
    A default implementation of a pagination serializer.
    """
    count = serializers.ReadOnlyField(source='paginator.count')
    next = NextPageField(source='*')
    previous = PreviousPageField(source='*')