class LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination
Documentation
Source code
A limit/offset based style. For example: http://api.example.org/accounts/?limit=100 http://api.example.org/accounts/?offset=400&limit=100
Ancestors (MRO)
- LimitOffsetPagination
- BasePagination
Attributes
Defined in | |
---|---|
default_limit = None
|
LimitOffsetPagination |
display_page_controls = False
|
BasePagination |
limit_query_description = 'Number of results to return per page.'
|
LimitOffsetPagination |
limit_query_param = 'limit'
|
LimitOffsetPagination |
max_limit = None
|
LimitOffsetPagination |
offset_query_description = 'The initial index from which to return the results.'
|
LimitOffsetPagination |
offset_query_param = 'offset'
|
LimitOffsetPagination |
template = 'rest_framework/pagination/numbers.html'
|
LimitOffsetPagination |
Methods
def
get_count(self, queryset):
¶
LimitOffsetPagination
Determine an object count, supporting either querysets or regular lists.
def get_count(self, queryset):
"""
Determine an object count, supporting either querysets or regular lists.
"""
try:
return queryset.count()
except (AttributeError, TypeError):
return len(queryset)
def
get_html_context(self):
¶
LimitOffsetPagination
def get_html_context(self):
base_url = self.request.build_absolute_uri()
if self.limit:
current = _divide_with_ceil(self.offset, self.limit) + 1
# The number of pages is a little bit fiddly.
# We need to sum both the number of pages from current offset to end
# plus the number of pages up to the current offset.
# When offset is not strictly divisible by the limit then we may
# end up introducing an extra page as an artifact.
final = (
_divide_with_ceil(self.count - self.offset, self.limit) +
_divide_with_ceil(self.offset, self.limit)
)
if final < 1:
final = 1
else:
current = 1
final = 1
if current > final:
current = final
def page_number_to_url(page_number):
if page_number == 1:
return remove_query_param(base_url, self.offset_query_param)
else:
offset = self.offset + ((page_number - current) * self.limit)
return replace_query_param(base_url, self.offset_query_param, offset)
page_numbers = _get_displayed_page_numbers(current, final)
page_links = _get_page_links(page_numbers, current, page_number_to_url)
return {
'previous_url': self.get_previous_link(),
'next_url': self.get_next_link(),
'page_links': page_links
}
def
get_limit(self, request):
¶
LimitOffsetPagination
def get_limit(self, request):
if self.limit_query_param:
try:
return _positive_int(
request.query_params[self.limit_query_param],
strict=True,
cutoff=self.max_limit
)
except (KeyError, ValueError):
pass
return self.default_limit
def
get_next_link(self):
¶
LimitOffsetPagination
def get_next_link(self):
if self.offset + self.limit >= self.count:
return None
url = self.request.build_absolute_uri()
url = replace_query_param(url, self.limit_query_param, self.limit)
offset = self.offset + self.limit
return replace_query_param(url, self.offset_query_param, offset)
def
get_offset(self, request):
¶
LimitOffsetPagination
def get_offset(self, request):
try:
return _positive_int(
request.query_params[self.offset_query_param],
)
except (KeyError, ValueError):
return 0
def
get_paginated_response(self, data):
¶
LimitOffsetPagination
def get_paginated_response(self, data):
return Response(OrderedDict([
('count', self.count),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))
BasePagination
def get_paginated_response(self, data): # pragma: no cover
raise NotImplementedError('get_paginated_response() must be implemented.')
def
get_paginated_response_schema(self, schema):
¶
LimitOffsetPagination
def get_paginated_response_schema(self, schema):
return {
'type': 'object',
'properties': {
'count': {
'type': 'integer',
'example': 123,
},
'next': {
'type': 'string',
'nullable': True,
},
'previous': {
'type': 'string',
'nullable': True,
},
'results': schema,
},
}
BasePagination
def get_paginated_response_schema(self, schema):
return schema
def
get_previous_link(self):
¶
LimitOffsetPagination
def get_previous_link(self):
if self.offset <= 0:
return None
url = self.request.build_absolute_uri()
url = replace_query_param(url, self.limit_query_param, self.limit)
if self.offset - self.limit <= 0:
return remove_query_param(url, self.offset_query_param)
offset = self.offset - self.limit
return replace_query_param(url, self.offset_query_param, offset)
def
get_results(self, data):
¶
BasePagination
def get_results(self, data):
return data['results']
def
get_schema_fields(self, view):
¶
LimitOffsetPagination
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
assert coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`'
return [
coreapi.Field(
name=self.limit_query_param,
required=False,
location='query',
schema=coreschema.Integer(
title='Limit',
description=force_str(self.limit_query_description)
)
),
coreapi.Field(
name=self.offset_query_param,
required=False,
location='query',
schema=coreschema.Integer(
title='Offset',
description=force_str(self.offset_query_description)
)
)
]
BasePagination
def get_schema_fields(self, view):
assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'
return []
def
get_schema_operation_parameters(self, view):
¶
LimitOffsetPagination
def get_schema_operation_parameters(self, view):
parameters = [
{
'name': self.limit_query_param,
'required': False,
'in': 'query',
'description': force_str(self.limit_query_description),
'schema': {
'type': 'integer',
},
},
{
'name': self.offset_query_param,
'required': False,
'in': 'query',
'description': force_str(self.offset_query_description),
'schema': {
'type': 'integer',
},
},
]
return parameters
BasePagination
def get_schema_operation_parameters(self, view):
return []
def
paginate_queryset(self, queryset, request, view=None):
¶
LimitOffsetPagination
def paginate_queryset(self, queryset, request, view=None):
self.count = self.get_count(queryset)
self.limit = self.get_limit(request)
if self.limit is None:
return None
self.offset = self.get_offset(request)
self.request = request
if self.count > self.limit and self.template is not None:
self.display_page_controls = True
if self.count == 0 or self.offset > self.count:
return []
return list(queryset[self.offset:self.offset + self.limit])
BasePagination
def paginate_queryset(self, queryset, request, view=None): # pragma: no cover
raise NotImplementedError('paginate_queryset() must be implemented.')
def
to_html(self):
¶
LimitOffsetPagination
def to_html(self):
template = loader.get_template(self.template)
context = self.get_html_context()
return template.render(context)
BasePagination
def to_html(self): # pragma: no cover
raise NotImplementedError('to_html() must be implemented to display page controls.')