aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorTom Christie2012-11-16 22:45:57 +0000
committerTom Christie2012-11-16 22:45:57 +0000
commit31f01bd6315f46bf28bb4c9c25a5298785fc4fc6 (patch)
tree8f2c0ef593402a23118d71c7f81734c30ef5d2cc /rest_framework
parent9973cf329a2133a900256b53236348ef3c870842 (diff)
downloaddjango-rest-framework-31f01bd6315f46bf28bb4c9c25a5298785fc4fc6.tar.bz2
Polishing to page size query parameters & more docs
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/generics.py32
-rw-r--r--rest_framework/mixins.py13
-rw-r--r--rest_framework/settings.py9
-rw-r--r--rest_framework/tests/pagination.py85
4 files changed, 43 insertions, 96 deletions
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index 9ad03f71..dcf4dfd9 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -14,6 +14,7 @@ class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
+ model = None
serializer_class = None
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
@@ -30,8 +31,10 @@ class GenericAPIView(views.APIView):
def get_serializer_class(self):
"""
Return the class to use for the serializer.
- Use `self.serializer_class`, falling back to constructing a
- model serializer class from `self.model_serializer_class`
+
+ Defaults to using `self.serializer_class`, falls back to constructing a
+ model serializer class using `self.model_serializer_class`, with
+ `self.model` as the model.
"""
serializer_class = self.serializer_class
@@ -58,29 +61,42 @@ class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView):
pagination_serializer_class = api_settings.DEFAULT_PAGINATION_SERIALIZER_CLASS
paginate_by = api_settings.PAGINATE_BY
+ paginate_by_param = api_settings.PAGINATE_BY_PARAM
filter_backend = api_settings.FILTER_BACKEND
def filter_queryset(self, queryset):
+ """
+ Given a queryset, filter it with whichever filter backend is in use.
+ """
if not self.filter_backend:
return queryset
backend = self.filter_backend()
return backend.filter_queryset(self.request, queryset, self)
- def get_pagination_serializer_class(self):
+ def get_pagination_serializer(self, page=None):
"""
- Return the class to use for the pagination serializer.
+ Return a serializer instance to use with paginated data.
"""
class SerializerClass(self.pagination_serializer_class):
class Meta:
object_serializer_class = self.get_serializer_class()
- return SerializerClass
-
- def get_pagination_serializer(self, page=None):
- pagination_serializer_class = self.get_pagination_serializer_class()
+ pagination_serializer_class = SerializerClass
context = self.get_serializer_context()
return pagination_serializer_class(instance=page, context=context)
+ def get_paginate_by(self, queryset):
+ """
+ Return the size of pages to use with pagination.
+ """
+ if self.paginate_by_param:
+ params = self.request.QUERY_PARAMS
+ try:
+ return int(params[self.paginate_by_param])
+ except (KeyError, ValueError):
+ pass
+ return self.paginate_by
+
class SingleObjectAPIView(SingleObjectMixin, GenericAPIView):
"""
diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py
index 0da4c2cc..53c4d984 100644
--- a/rest_framework/mixins.py
+++ b/rest_framework/mixins.py
@@ -7,7 +7,6 @@ which allows mixin classes to be composed in interesting ways.
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
-from rest_framework.settings import api_settings
class CreateModelMixin(object):
@@ -40,7 +39,6 @@ class ListModelMixin(object):
Should be mixed in with `MultipleObjectAPIView`.
"""
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):
queryset = self.get_queryset()
@@ -66,17 +64,6 @@ class ListModelMixin(object):
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):
"""
diff --git a/rest_framework/settings.py b/rest_framework/settings.py
index 8883b963..ee24a4ad 100644
--- a/rest_framework/settings.py
+++ b/rest_framework/settings.py
@@ -54,12 +54,19 @@ DEFAULTS = {
'user': None,
'anon': None,
},
+
+ # Pagination
'PAGINATE_BY': None,
+ 'PAGINATE_BY_PARAM': None,
+
+ # Filtering
'FILTER_BACKEND': None,
+ # Authentication
'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
'UNAUTHENTICATED_TOKEN': None,
+ # Browser enhancements
'FORM_METHOD_OVERRIDE': '_method',
'FORM_CONTENT_OVERRIDE': '_content',
'FORM_CONTENTTYPE_OVERRIDE': '_content_type',
@@ -67,8 +74,6 @@ DEFAULTS = {
'URL_FORMAT_OVERRIDE': 'format',
'FORMAT_SUFFIX_KWARG': 'format',
-
- 'PAGE_SIZE_KWARG': 'page_size'
}
diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py
index 8aae2147..3062007d 100644
--- a/rest_framework/tests/pagination.py
+++ b/rest_framework/tests/pagination.py
@@ -36,25 +36,17 @@ if django_filters:
class DefaultPageSizeKwargView(generics.ListAPIView):
"""
- View for testing default page_size usage
+ View for testing default paginate_by_param usage
"""
model = BasicModel
-class CustomPageSizeKwargView(generics.ListAPIView):
+class PaginateByParamView(generics.ListAPIView):
"""
- View for testing custom page_size usage
+ View for testing custom paginate_by_param usage
"""
model = BasicModel
- page_size_kwarg = 'ps'
-
-
-class NonePageSizeKwargView(generics.ListAPIView):
- """
- View for testing None page_size usage
- """
- model = BasicModel
- page_size_kwarg = None
+ paginate_by_param = 'page_size'
class IntegrationTestPagination(TestCase):
@@ -181,9 +173,9 @@ class UnitTestPagination(TestCase):
self.assertEquals(serializer.data['results'], self.objects[20:])
-class TestDefaultPageSizeKwarg(TestCase):
+class TestUnpaginated(TestCase):
"""
- Tests for list views with default page size kwarg
+ Tests for list views without pagination.
"""
def setUp(self):
@@ -199,26 +191,17 @@ class TestDefaultPageSizeKwarg(TestCase):
]
self.view = DefaultPageSizeKwargView.as_view()
- def test_default_page_size(self):
+ def test_unpaginated(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()
+ response = self.view(request)
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):
+class TestCustomPaginateByParam(TestCase):
"""
Tests for list views with default page size kwarg
"""
@@ -234,7 +217,7 @@ class TestCustomPageSizeKwarg(TestCase):
{'id': obj.id, 'text': obj.text}
for obj in self.objects.all()
]
- self.view = CustomPageSizeKwargView.as_view()
+ self.view = PaginateByParamView.as_view()
def test_default_page_size(self):
"""
@@ -245,55 +228,11 @@ class TestCustomPageSizeKwarg(TestCase):
response = self.view(request).render()
self.assertEquals(response.data, self.data)
- def test_disabled_default_page_size_kwarg(self):
+ def test_paginate_by_param(self):
"""
- If page_size_kwarg is set set, the default page_size kwarg should not work.
+ If paginate_by_param is set, the new kwarg should limit per view requests.
"""
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)