mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
Merge pull request #412 from minddust/custom_page_size_per_request
support for custom page size per request
This commit is contained in:
commit
9973cf329a
|
@ -147,6 +147,10 @@ Provides a `.list(request, *args, **kwargs)` method, that implements listing a q
|
||||||
|
|
||||||
Should be mixed in with [MultipleObjectAPIView].
|
Should be mixed in with [MultipleObjectAPIView].
|
||||||
|
|
||||||
|
**Arguments**:
|
||||||
|
|
||||||
|
* `page_size_kwarg` - Allows you to overwrite the global settings `PAGE_SIZE_KWARG` for a specific view. You can also turn it off for a specific view by setting it to `None`. Default is `page_size`.
|
||||||
|
|
||||||
## CreateModelMixin
|
## CreateModelMixin
|
||||||
|
|
||||||
Provides a `.create(request, *args, **kwargs)` method, that implements creating and saving a new model instance.
|
Provides a `.create(request, *args, **kwargs)` method, that implements creating and saving a new model instance.
|
||||||
|
|
|
@ -150,4 +150,14 @@ Default: `'accept'`
|
||||||
|
|
||||||
Default: `'format'`
|
Default: `'format'`
|
||||||
|
|
||||||
|
## PAGE_SIZE_KWARG
|
||||||
|
|
||||||
|
Allows you to globally pass a page size parameter for an individual request.
|
||||||
|
|
||||||
|
The name of the GET parameter of views which inherit ListModelMixin for requesting data with an individual page size.
|
||||||
|
|
||||||
|
If the value if this setting is `None` the passing a page size is turned off by default.
|
||||||
|
|
||||||
|
Default: `'page_size'`
|
||||||
|
|
||||||
[cite]: http://www.python.org/dev/peps/pep-0020/
|
[cite]: http://www.python.org/dev/peps/pep-0020/
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
## Master
|
## Master
|
||||||
|
|
||||||
* Support for `read_only_fields` on `ModelSerializer` classes.
|
* Support for `read_only_fields` on `ModelSerializer` classes.
|
||||||
|
* Support for individual page sizes per request via `page_size` GET parameter in views which inherit ListModelMixin.
|
||||||
|
|
||||||
## 2.1.2
|
## 2.1.2
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ which allows mixin classes to be composed in interesting ways.
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
|
||||||
class CreateModelMixin(object):
|
class CreateModelMixin(object):
|
||||||
|
@ -39,6 +40,7 @@ class ListModelMixin(object):
|
||||||
Should be mixed in with `MultipleObjectAPIView`.
|
Should be mixed in with `MultipleObjectAPIView`.
|
||||||
"""
|
"""
|
||||||
empty_error = u"Empty list and '%(class_name)s.allow_empty' is False."
|
empty_error = u"Empty list and '%(class_name)s.allow_empty' is False."
|
||||||
|
page_size_kwarg = api_settings.PAGE_SIZE_KWARG
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
|
@ -64,6 +66,17 @@ class ListModelMixin(object):
|
||||||
|
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def get_paginate_by(self, queryset):
|
||||||
|
if self.page_size_kwarg is not None:
|
||||||
|
page_size_kwarg = self.request.QUERY_PARAMS.get(self.page_size_kwarg)
|
||||||
|
if page_size_kwarg:
|
||||||
|
try:
|
||||||
|
page_size = int(page_size_kwarg)
|
||||||
|
return page_size
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return super(ListModelMixin, self).get_paginate_by(queryset)
|
||||||
|
|
||||||
|
|
||||||
class RetrieveModelMixin(object):
|
class RetrieveModelMixin(object):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -66,7 +66,9 @@ DEFAULTS = {
|
||||||
'URL_ACCEPT_OVERRIDE': 'accept',
|
'URL_ACCEPT_OVERRIDE': 'accept',
|
||||||
'URL_FORMAT_OVERRIDE': 'format',
|
'URL_FORMAT_OVERRIDE': 'format',
|
||||||
|
|
||||||
'FORMAT_SUFFIX_KWARG': 'format'
|
'FORMAT_SUFFIX_KWARG': 'format',
|
||||||
|
|
||||||
|
'PAGE_SIZE_KWARG': 'page_size'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,29 @@ if django_filters:
|
||||||
filter_backend = filters.DjangoFilterBackend
|
filter_backend = filters.DjangoFilterBackend
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultPageSizeKwargView(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
View for testing default page_size usage
|
||||||
|
"""
|
||||||
|
model = BasicModel
|
||||||
|
|
||||||
|
|
||||||
|
class CustomPageSizeKwargView(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
View for testing custom page_size usage
|
||||||
|
"""
|
||||||
|
model = BasicModel
|
||||||
|
page_size_kwarg = 'ps'
|
||||||
|
|
||||||
|
|
||||||
|
class NonePageSizeKwargView(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
View for testing None page_size usage
|
||||||
|
"""
|
||||||
|
model = BasicModel
|
||||||
|
page_size_kwarg = None
|
||||||
|
|
||||||
|
|
||||||
class IntegrationTestPagination(TestCase):
|
class IntegrationTestPagination(TestCase):
|
||||||
"""
|
"""
|
||||||
Integration tests for paginated list views.
|
Integration tests for paginated list views.
|
||||||
|
@ -135,7 +158,7 @@ class IntegrationTestPaginationAndFiltering(TestCase):
|
||||||
|
|
||||||
class UnitTestPagination(TestCase):
|
class UnitTestPagination(TestCase):
|
||||||
"""
|
"""
|
||||||
Unit tests for pagination of primative objects.
|
Unit tests for pagination of primitive objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -156,3 +179,121 @@ class UnitTestPagination(TestCase):
|
||||||
self.assertEquals(serializer.data['next'], None)
|
self.assertEquals(serializer.data['next'], None)
|
||||||
self.assertEquals(serializer.data['previous'], '?page=2')
|
self.assertEquals(serializer.data['previous'], '?page=2')
|
||||||
self.assertEquals(serializer.data['results'], self.objects[20:])
|
self.assertEquals(serializer.data['results'], self.objects[20:])
|
||||||
|
|
||||||
|
|
||||||
|
class TestDefaultPageSizeKwarg(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for list views with default page size kwarg
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create 13 BasicModel instances.
|
||||||
|
"""
|
||||||
|
for i in range(13):
|
||||||
|
BasicModel(text=i).save()
|
||||||
|
self.objects = BasicModel.objects
|
||||||
|
self.data = [
|
||||||
|
{'id': obj.id, 'text': obj.text}
|
||||||
|
for obj in self.objects.all()
|
||||||
|
]
|
||||||
|
self.view = DefaultPageSizeKwargView.as_view()
|
||||||
|
|
||||||
|
def test_default_page_size(self):
|
||||||
|
"""
|
||||||
|
Tests the default page size for this view.
|
||||||
|
no page size --> no limit --> no meta data
|
||||||
|
"""
|
||||||
|
request = factory.get('/')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data, self.data)
|
||||||
|
|
||||||
|
def test_default_page_size_kwarg(self):
|
||||||
|
"""
|
||||||
|
If page_size_kwarg is set not set, the default page_size kwarg should limit per view requests.
|
||||||
|
"""
|
||||||
|
request = factory.get('/?page_size=5')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data['count'], 13)
|
||||||
|
self.assertEquals(response.data['results'], self.data[:5])
|
||||||
|
|
||||||
|
|
||||||
|
class TestCustomPageSizeKwarg(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for list views with default page size kwarg
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create 13 BasicModel instances.
|
||||||
|
"""
|
||||||
|
for i in range(13):
|
||||||
|
BasicModel(text=i).save()
|
||||||
|
self.objects = BasicModel.objects
|
||||||
|
self.data = [
|
||||||
|
{'id': obj.id, 'text': obj.text}
|
||||||
|
for obj in self.objects.all()
|
||||||
|
]
|
||||||
|
self.view = CustomPageSizeKwargView.as_view()
|
||||||
|
|
||||||
|
def test_default_page_size(self):
|
||||||
|
"""
|
||||||
|
Tests the default page size for this view.
|
||||||
|
no page size --> no limit --> no meta data
|
||||||
|
"""
|
||||||
|
request = factory.get('/')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data, self.data)
|
||||||
|
|
||||||
|
def test_disabled_default_page_size_kwarg(self):
|
||||||
|
"""
|
||||||
|
If page_size_kwarg is set set, the default page_size kwarg should not work.
|
||||||
|
"""
|
||||||
|
request = factory.get('/?page_size=5')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data, self.data)
|
||||||
|
|
||||||
|
def test_custom_page_size_kwarg(self):
|
||||||
|
"""
|
||||||
|
If page_size_kwarg is set set, the new kwarg should limit per view requests.
|
||||||
|
"""
|
||||||
|
request = factory.get('/?ps=5')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data['count'], 13)
|
||||||
|
self.assertEquals(response.data['results'], self.data[:5])
|
||||||
|
|
||||||
|
|
||||||
|
class TestNonePageSizeKwarg(TestCase):
|
||||||
|
"""
|
||||||
|
Tests for list views with default page size kwarg
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create 13 BasicModel instances.
|
||||||
|
"""
|
||||||
|
for i in range(13):
|
||||||
|
BasicModel(text=i).save()
|
||||||
|
self.objects = BasicModel.objects
|
||||||
|
self.data = [
|
||||||
|
{'id': obj.id, 'text': obj.text}
|
||||||
|
for obj in self.objects.all()
|
||||||
|
]
|
||||||
|
self.view = NonePageSizeKwargView.as_view()
|
||||||
|
|
||||||
|
def test_default_page_size(self):
|
||||||
|
"""
|
||||||
|
Tests the default page size for this view.
|
||||||
|
no page size --> no limit --> no meta data
|
||||||
|
"""
|
||||||
|
request = factory.get('/')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data, self.data)
|
||||||
|
|
||||||
|
def test_none_page_size_kwarg(self):
|
||||||
|
"""
|
||||||
|
If page_size_kwarg is set to None, custom page_size per request should be disabled.
|
||||||
|
"""
|
||||||
|
request = factory.get('/?page_size=5')
|
||||||
|
response = self.view(request).render()
|
||||||
|
self.assertEquals(response.data, self.data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user