Add get_django_paginator_class method to PageNumberPagination

This enables the pagination class to be overridden conditionally.
This commit is contained in:
George Dunning 2022-03-13 15:25:41 +00:00
parent 0e3bc2b1e0
commit 648ce5864e
2 changed files with 49 additions and 2 deletions

View File

@ -193,11 +193,13 @@ class PageNumberPagination(BasePagination):
Paginate a queryset if required, either returning a Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view. page object, or `None` if pagination is not configured for this view.
""" """
self.request = request
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
paginator = self.django_paginator_class(queryset, page_size) paginator = self.get_django_paginator_class()(queryset, page_size)
page_number = self.get_page_number(request, paginator) page_number = self.get_page_number(request, paginator)
try: try:
@ -212,7 +214,6 @@ class PageNumberPagination(BasePagination):
# The browsable API should display pagination controls. # The browsable API should display pagination controls.
self.display_page_controls = True self.display_page_controls = True
self.request = request
return list(self.page) return list(self.page)
def get_page_number(self, request, paginator): def get_page_number(self, request, paginator):
@ -304,6 +305,9 @@ class PageNumberPagination(BasePagination):
'page_links': page_links 'page_links': page_links
} }
def get_django_paginator_class(self):
return self.django_paginator_class
def to_html(self): def to_html(self):
template = loader.get_template(self.template) template = loader.get_template(self.template)
context = self.get_html_context() context = self.get_html_context()

View File

@ -308,6 +308,8 @@ class TestPageNumberPaginationOverride:
# we will only return one page, with one item # we will only return one page, with one item
count = 1 count = 1
self.paginator = OverriddenDjangoPaginator
class ExamplePagination(pagination.PageNumberPagination): class ExamplePagination(pagination.PageNumberPagination):
django_paginator_class = OverriddenDjangoPaginator django_paginator_class = OverriddenDjangoPaginator
page_size = 5 page_size = 5
@ -352,6 +354,47 @@ class TestPageNumberPaginationOverride:
with pytest.raises(exceptions.NotFound): with pytest.raises(exceptions.NotFound):
self.paginate_queryset(request) self.paginate_queryset(request)
def test_no_page_number_override_using_get_django_paginator_class(self):
paginator = self.paginator
class UrlSpecifiedPagination(pagination.PageNumberPagination):
page_size = 5
def get_django_paginator_class(self):
"""
Set the pagination class based on URL parameters.
"""
if self.request.GET.get("pagination_mode") == "overridden":
return paginator
else:
raise NotImplementedError(
"The test data should not trigger this branch."
)
self.pagination = UrlSpecifiedPagination()
request = Request(factory.get('/', data={'pagination_mode': 'overridden'}))
queryset = self.paginate_queryset(request)
content = self.get_paginated_content(queryset)
context = self.get_html_context()
assert queryset == [1]
assert content == {
'results': [1, ],
'previous': None,
'next': None,
'count': 1
}
assert context == {
'previous_url': None,
'next_url': None,
'page_links': [
PageLink('http://testserver/?pagination_mode=overridden', 1, True, False),
]
}
assert not self.pagination.display_page_controls
assert isinstance(self.pagination.to_html(), str)
class TestLimitOffset: class TestLimitOffset:
""" """