From 648ce5864e4b165e1c626e072385e2cf99679a88 Mon Sep 17 00:00:00 2001 From: George Dunning Date: Sun, 13 Mar 2022 15:25:41 +0000 Subject: [PATCH] Add get_django_paginator_class method to PageNumberPagination This enables the pagination class to be overridden conditionally. --- rest_framework/pagination.py | 8 +++++-- tests/test_pagination.py | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index e815d8d5c..c2357c9ca 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -193,11 +193,13 @@ class PageNumberPagination(BasePagination): Paginate a queryset if required, either returning a page object, or `None` if pagination is not configured for this view. """ + self.request = request + page_size = self.get_page_size(request) if not page_size: 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) try: @@ -212,7 +214,6 @@ class PageNumberPagination(BasePagination): # The browsable API should display pagination controls. self.display_page_controls = True - self.request = request return list(self.page) def get_page_number(self, request, paginator): @@ -304,6 +305,9 @@ class PageNumberPagination(BasePagination): 'page_links': page_links } + def get_django_paginator_class(self): + return self.django_paginator_class + def to_html(self): template = loader.get_template(self.template) context = self.get_html_context() diff --git a/tests/test_pagination.py b/tests/test_pagination.py index c028f0ea8..a589adccd 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -308,6 +308,8 @@ class TestPageNumberPaginationOverride: # we will only return one page, with one item count = 1 + self.paginator = OverriddenDjangoPaginator + class ExamplePagination(pagination.PageNumberPagination): django_paginator_class = OverriddenDjangoPaginator page_size = 5 @@ -352,6 +354,47 @@ class TestPageNumberPaginationOverride: with pytest.raises(exceptions.NotFound): 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: """