diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index c54894efc..d749d53ac 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -723,3 +723,35 @@ class CursorPagination(BasePagination): def get_fields(self, view): return [self.cursor_query_param] + + +class HybridPagination(PageNumberPagination, LimitOffsetPagination): + """ + Basically allows both pagination method to work within a single pagination class. + By default it uses the PageNumberPagination + When 'offset' is used in request.GET, it will switch to use LimitOffsetPagination + """ + proxy = PageNumberPagination + + def paginate_queryset(self, queryset, request, *args, **kwargs): + if 'offset' in request.GET or 'limit' in request.GET: + self.proxy = LimitOffsetPagination + return self.proxy.paginate_queryset(self, queryset, request, *args, **kwargs) + + def get_paginated_response(self, *args, **kwargs): + return self.proxy.get_paginated_response(self, *args, **kwargs) + + def to_html(self, *args, **kwargs): + return self.proxy.to_html(self, *args, **kwargs) + + def get_results(self, *args, **kwargs): + return self.proxy.get_results(self, *args, **kwargs) + + def get_next_link(self, *args, **kwargs): + return self.proxy.get_next_link(self, *args, **kwargs) + + def get_previous_link(self, *args, **kwargs): + return self.proxy.get_previous_link(self, *args, **kwargs) + + def get_html_context(self): + return self.proxy.get_html_context(self) diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 170d95899..c73b9dfd7 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -754,3 +754,22 @@ def test_get_displayed_page_numbers(): assert displayed_page_numbers(7, 9) == [1, None, 6, 7, 8, 9] assert displayed_page_numbers(8, 9) == [1, None, 7, 8, 9] assert displayed_page_numbers(9, 9) == [1, None, 7, 8, 9] + + +class TestCombinedPaginationPageNumber(TestPageNumberPagination): + def setup(self): + class ExamplePagination(pagination.HybridPagination): + page_size = 5 + + self.pagination = ExamplePagination() + self.queryset = range(1, 101) + + +class TestCombinedPaginationLimitOffset(TestLimitOffset): + def setup(self): + class ExamplePagination(pagination.HybridPagination): + default_limit = 10 + max_limit = 15 + + self.pagination = ExamplePagination() + self.queryset = range(1, 101)