From a3ad476c88d64bb6c5f70e7925cbb5a1da29aa23 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 9 Apr 2019 10:30:26 +0200 Subject: [PATCH] More configurable pagination --- api/funkwhale_api/common/pagination.py | 27 ++++++++++++++++++++++-- api/funkwhale_api/music/views.py | 1 + api/tests/common/test_pagination.py | 29 ++++++++++++++++++++++++++ api/tests/music/test_views.py | 2 +- 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 api/tests/common/test_pagination.py diff --git a/api/funkwhale_api/common/pagination.py b/api/funkwhale_api/common/pagination.py index e5068bce2..ec7c27dc4 100644 --- a/api/funkwhale_api/common/pagination.py +++ b/api/funkwhale_api/common/pagination.py @@ -1,6 +1,29 @@ -from rest_framework.pagination import PageNumberPagination +from rest_framework.pagination import PageNumberPagination, _positive_int class FunkwhalePagination(PageNumberPagination): page_size_query_param = "page_size" - max_page_size = 50 + default_max_page_size = 50 + default_page_size = None + view = None + + def paginate_queryset(self, queryset, request, view=None): + self.view = view + return super().paginate_queryset(queryset, request, view) + + def get_page_size(self, request): + max_page_size = ( + getattr(self.view, "max_page_size", 0) or self.default_max_page_size + ) + page_size = getattr(self.view, "default_page_size", 0) or max_page_size + if self.page_size_query_param: + try: + return _positive_int( + request.query_params[self.page_size_query_param], + strict=True, + cutoff=max_page_size, + ) + except (KeyError, ValueError): + pass + + return page_size diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index b5242eeb1..2f0e67cb9 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -524,6 +524,7 @@ class LicenseViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = serializers.LicenseSerializer queryset = models.License.objects.all().order_by("code") lookup_value_regex = ".*" + max_page_size = 1000 def get_queryset(self): # ensure our licenses are up to date in DB diff --git a/api/tests/common/test_pagination.py b/api/tests/common/test_pagination.py new file mode 100644 index 000000000..cacbe740c --- /dev/null +++ b/api/tests/common/test_pagination.py @@ -0,0 +1,29 @@ +import pytest + +from funkwhale_api.common import pagination + + +@pytest.mark.parametrize( + "view_max_page_size, view_default_page_size, request_page_size, expected", + [ + (50, 50, None, 50), + (50, 25, None, 25), + (25, None, None, 25), + (50, 25, 100, 50), + (50, None, 100, 50), + (50, 25, 33, 33), + ], +) +def test_funkwhale_pagination_uses_view_page_size( + view_max_page_size, view_default_page_size, request_page_size, expected, mocker +): + p = pagination.FunkwhalePagination() + + p.view = mocker.Mock( + max_page_size=view_max_page_size, default_page_size=view_default_page_size + ) + query = {} + if request_page_size: + query["page_size"] = request_page_size + request = mocker.Mock(query_params=query) + assert p.get_page_size(request) == expected diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 7b12c6c8f..2c3a61c05 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -612,7 +612,7 @@ def test_list_licenses(api_client, preferences, mocker): expected = [ serializers.LicenseSerializer(l.conf).data - for l in models.License.objects.order_by("code")[:25] + for l in models.License.objects.order_by("code") ] url = reverse("api:v1:licenses-list")