Commit 4c53fb88 by Tom Christie

Tweak MAX_PAGINATE_BY behavior in edge case.

Always respect `paginate_by` settings if client does not specify page
size.  (Even if the developer has misconfigured, so that `paginate_by >
max`.)
parent e1b54f2a
...@@ -14,13 +14,15 @@ from rest_framework.settings import api_settings ...@@ -14,13 +14,15 @@ from rest_framework.settings import api_settings
import warnings import warnings
def strict_positive_int(integer_string): def strict_positive_int(integer_string, cutoff=None):
""" """
Cast a string to a strictly positive integer. Cast a string to a strictly positive integer.
""" """
ret = int(integer_string) ret = int(integer_string)
if ret <= 0: if ret <= 0:
raise ValueError() raise ValueError()
if cutoff:
ret = min(ret, cutoff)
return ret return ret
def get_object_or_404(queryset, **filter_kwargs): def get_object_or_404(queryset, **filter_kwargs):
...@@ -206,21 +208,15 @@ class GenericAPIView(views.APIView): ...@@ -206,21 +208,15 @@ class GenericAPIView(views.APIView):
PendingDeprecationWarning, stacklevel=2) PendingDeprecationWarning, stacklevel=2)
if self.paginate_by_param: if self.paginate_by_param:
query_params = self.request.QUERY_PARAMS
try: try:
paginate_by_param = int(query_params[self.paginate_by_param]) return strict_positive_int(
self.request.QUERY_PARAMS[self.paginate_by_param],
cutoff=self.max_paginate_by
)
except (KeyError, ValueError): except (KeyError, ValueError):
pass pass
else:
if self.max_paginate_by is not None:
return min(self.max_paginate_by, paginate_by_param)
else:
return paginate_by_param
if self.max_paginate_by: return self.paginate_by
return min(self.max_paginate_by, self.paginate_by)
else:
return self.paginate_by
def get_serializer_class(self): def get_serializer_class(self):
""" """
......
...@@ -47,8 +47,8 @@ class MaxPaginateByView(generics.ListAPIView): ...@@ -47,8 +47,8 @@ class MaxPaginateByView(generics.ListAPIView):
View for testing custom max_paginate_by usage View for testing custom max_paginate_by usage
""" """
model = BasicModel model = BasicModel
paginate_by = 5 paginate_by = 3
max_paginate_by = 3 max_paginate_by = 5
paginate_by_param = 'page_size' paginate_by_param = 'page_size'
...@@ -343,16 +343,17 @@ class TestMaxPaginateByParam(TestCase): ...@@ -343,16 +343,17 @@ class TestMaxPaginateByParam(TestCase):
def test_max_paginate_by(self): def test_max_paginate_by(self):
""" """
If max_paginate_by is set and it less than paginate_by, new kwarg should limit requests for review. If max_paginate_by is set, it should limit page size for the view.
""" """
request = factory.get('/?page_size=10') request = factory.get('/?page_size=10')
response = self.view(request).render() response = self.view(request).render()
self.assertEqual(response.data['count'], 13) self.assertEqual(response.data['count'], 13)
self.assertEqual(response.data['results'], self.data[:3]) self.assertEqual(response.data['results'], self.data[:5])
def test_max_paginate_by_without_page_size_param(self): def test_max_paginate_by_without_page_size_param(self):
""" """
If max_paginate_by is set, new kwarg should limit requests for review. If max_paginate_by is set, but client does not specifiy page_size,
standard `paginate_by` behavior should be used.
""" """
request = factory.get('/') request = factory.get('/')
response = self.view(request).render() response = self.view(request).render()
......
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