Commit 8b0f25aa by Tom Christie

More pagination tests & cleanup

parent 50db8c09
...@@ -151,6 +151,9 @@ class GenericAPIView(views.APIView): ...@@ -151,6 +151,9 @@ class GenericAPIView(views.APIView):
@property @property
def paginator(self): def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'): if not hasattr(self, '_paginator'):
if self.pagination_class is None: if self.pagination_class is None:
self._paginator = None self._paginator = None
...@@ -159,11 +162,18 @@ class GenericAPIView(views.APIView): ...@@ -159,11 +162,18 @@ class GenericAPIView(views.APIView):
return self._paginator return self._paginator
def paginate_queryset(self, queryset): def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None: if self.paginator is None:
return queryset return None
return self.paginator.paginate_queryset(queryset, self.request, view=self) return self.paginator.paginate_queryset(queryset, self.request, view=self)
def get_paginated_response(self, data): def get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data) return self.paginator.get_paginated_response(data)
......
...@@ -131,13 +131,13 @@ PAGE_BREAK = PageLink(url=None, number=None, is_active=False, is_break=True) ...@@ -131,13 +131,13 @@ PAGE_BREAK = PageLink(url=None, number=None, is_active=False, is_break=True)
class BasePagination(object): class BasePagination(object):
display_page_controls = False display_page_controls = False
def paginate_queryset(self, queryset, request, view=None): def paginate_queryset(self, queryset, request, view=None): # pragma: no cover
raise NotImplemented('paginate_queryset() must be implemented.') raise NotImplemented('paginate_queryset() must be implemented.')
def get_paginated_response(self, data): def get_paginated_response(self, data): # pragma: no cover
raise NotImplemented('get_paginated_response() must be implemented.') raise NotImplemented('get_paginated_response() must be implemented.')
def to_html(self): def to_html(self): # pragma: no cover
raise NotImplemented('to_html() must be implemented to display page controls.') raise NotImplemented('to_html() must be implemented to display page controls.')
...@@ -168,10 +168,11 @@ class PageNumberPagination(BasePagination): ...@@ -168,10 +168,11 @@ class PageNumberPagination(BasePagination):
template = 'rest_framework/pagination/numbers.html' template = 'rest_framework/pagination/numbers.html'
def paginate_queryset(self, queryset, request, view=None): def _handle_backwards_compat(self, view):
""" """
Paginate a queryset if required, either returning a Prior to version 3.1, pagination was handled in the view, and the
page object, or `None` if pagination is not configured for this view. attributes were set there. The attributes should now be set on
the pagination class, but the old style is still pending deprecation.
""" """
for attr in ( for attr in (
'paginate_by', 'page_query_param', 'paginate_by', 'page_query_param',
...@@ -180,6 +181,13 @@ class PageNumberPagination(BasePagination): ...@@ -180,6 +181,13 @@ class PageNumberPagination(BasePagination):
if hasattr(view, attr): if hasattr(view, attr):
setattr(self, attr, getattr(view, attr)) setattr(self, attr, getattr(view, attr))
def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
self._handle_backwards_compat(view)
page_size = self.get_page_size(request) page_size = self.get_page_size(request)
if not page_size: if not page_size:
return None return None
...@@ -277,7 +285,6 @@ class LimitOffsetPagination(BasePagination): ...@@ -277,7 +285,6 @@ class LimitOffsetPagination(BasePagination):
limit_query_param = 'limit' limit_query_param = 'limit'
offset_query_param = 'offset' offset_query_param = 'offset'
max_limit = None max_limit = None
template = 'rest_framework/pagination/numbers.html' template = 'rest_framework/pagination/numbers.html'
def paginate_queryset(self, queryset, request, view=None): def paginate_queryset(self, queryset, request, view=None):
...@@ -340,7 +347,15 @@ class LimitOffsetPagination(BasePagination): ...@@ -340,7 +347,15 @@ class LimitOffsetPagination(BasePagination):
def get_html_context(self): def get_html_context(self):
base_url = self.request.build_absolute_uri() base_url = self.request.build_absolute_uri()
current = _divide_with_ceil(self.offset, self.limit) + 1 current = _divide_with_ceil(self.offset, self.limit) + 1
final = _divide_with_ceil(self.count, self.limit) # 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)
)
def page_number_to_url(page_number): def page_number_to_url(page_number):
if page_number == 1: if page_number == 1:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment