2012-10-09 00:00:55 +04:00
|
|
|
import datetime
|
2012-10-11 15:55:16 +04:00
|
|
|
from decimal import Decimal
|
2012-10-01 18:49:19 +04:00
|
|
|
from django.core.paginator import Paginator
|
2012-09-30 20:31:28 +04:00
|
|
|
from django.test import TestCase
|
|
|
|
from django.test.client import RequestFactory
|
2012-11-08 01:07:24 +04:00
|
|
|
from django.utils import unittest
|
2012-11-09 01:46:53 +04:00
|
|
|
from rest_framework import generics, status, pagination, filters
|
2012-11-08 01:07:24 +04:00
|
|
|
from rest_framework.compat import django_filters
|
2012-10-09 00:00:55 +04:00
|
|
|
from rest_framework.tests.models import BasicModel, FilterableItem
|
2012-09-30 20:31:28 +04:00
|
|
|
|
|
|
|
factory = RequestFactory()
|
|
|
|
|
|
|
|
|
2012-10-03 12:26:15 +04:00
|
|
|
class RootView(generics.ListCreateAPIView):
|
2012-09-30 20:31:28 +04:00
|
|
|
"""
|
|
|
|
Example description for OPTIONS.
|
|
|
|
"""
|
|
|
|
model = BasicModel
|
|
|
|
paginate_by = 10
|
|
|
|
|
|
|
|
|
2012-11-08 01:07:24 +04:00
|
|
|
if django_filters:
|
|
|
|
class DecimalFilter(django_filters.FilterSet):
|
|
|
|
decimal = django_filters.NumberFilter(lookup_type='lt')
|
2012-10-09 00:00:55 +04:00
|
|
|
|
2012-11-08 01:07:24 +04:00
|
|
|
class Meta:
|
|
|
|
model = FilterableItem
|
|
|
|
fields = ['text', 'decimal', 'date']
|
2012-10-09 00:00:55 +04:00
|
|
|
|
2012-11-08 01:07:24 +04:00
|
|
|
class FilterFieldsRootView(generics.ListCreateAPIView):
|
|
|
|
model = FilterableItem
|
|
|
|
paginate_by = 10
|
|
|
|
filter_class = DecimalFilter
|
2012-11-09 01:46:53 +04:00
|
|
|
filter_backend = filters.DjangoFilterBackend
|
2012-10-09 00:00:55 +04:00
|
|
|
|
|
|
|
|
2012-11-15 17:35:34 +04:00
|
|
|
class DefaultPageSizeKwargView(generics.ListAPIView):
|
|
|
|
"""
|
2012-11-17 02:45:57 +04:00
|
|
|
View for testing default paginate_by_param usage
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
model = BasicModel
|
|
|
|
|
|
|
|
|
2012-11-17 02:45:57 +04:00
|
|
|
class PaginateByParamView(generics.ListAPIView):
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
2012-11-17 02:45:57 +04:00
|
|
|
View for testing custom paginate_by_param usage
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
model = BasicModel
|
2012-11-17 02:45:57 +04:00
|
|
|
paginate_by_param = 'page_size'
|
2012-11-15 17:35:34 +04:00
|
|
|
|
|
|
|
|
2012-10-01 18:49:19 +04:00
|
|
|
class IntegrationTestPagination(TestCase):
|
|
|
|
"""
|
|
|
|
Integration tests for paginated list views.
|
|
|
|
"""
|
|
|
|
|
2012-09-30 20:31:28 +04:00
|
|
|
def setUp(self):
|
|
|
|
"""
|
2012-10-09 00:00:55 +04:00
|
|
|
Create 26 BasicModel instances.
|
2012-09-30 20:31:28 +04:00
|
|
|
"""
|
|
|
|
for char in 'abcdefghijklmnopqrstuvwxyz':
|
|
|
|
BasicModel(text=char * 3).save()
|
|
|
|
self.objects = BasicModel.objects
|
|
|
|
self.data = [
|
|
|
|
{'id': obj.id, 'text': obj.text}
|
|
|
|
for obj in self.objects.all()
|
|
|
|
]
|
|
|
|
self.view = RootView.as_view()
|
|
|
|
|
|
|
|
def test_get_paginated_root_view(self):
|
|
|
|
"""
|
2012-10-03 12:26:15 +04:00
|
|
|
GET requests to paginated ListCreateAPIView should return paginated results.
|
2012-09-30 20:31:28 +04:00
|
|
|
"""
|
|
|
|
request = factory.get('/')
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 26)
|
|
|
|
self.assertEquals(response.data['results'], self.data[:10])
|
|
|
|
self.assertNotEquals(response.data['next'], None)
|
|
|
|
self.assertEquals(response.data['previous'], None)
|
|
|
|
|
|
|
|
request = factory.get(response.data['next'])
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 26)
|
|
|
|
self.assertEquals(response.data['results'], self.data[10:20])
|
|
|
|
self.assertNotEquals(response.data['next'], None)
|
|
|
|
self.assertNotEquals(response.data['previous'], None)
|
|
|
|
|
|
|
|
request = factory.get(response.data['next'])
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 26)
|
|
|
|
self.assertEquals(response.data['results'], self.data[20:])
|
|
|
|
self.assertEquals(response.data['next'], None)
|
|
|
|
self.assertNotEquals(response.data['previous'], None)
|
2012-10-01 18:49:19 +04:00
|
|
|
|
2012-10-11 13:32:51 +04:00
|
|
|
|
2012-10-09 00:00:55 +04:00
|
|
|
class IntegrationTestPaginationAndFiltering(TestCase):
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""
|
|
|
|
Create 50 FilterableItem instances.
|
|
|
|
"""
|
2012-10-11 16:19:29 +04:00
|
|
|
base_data = ('a', Decimal('0.25'), datetime.date(2012, 10, 8))
|
2012-10-09 00:00:55 +04:00
|
|
|
for i in range(26):
|
|
|
|
text = chr(i + ord(base_data[0])) * 3 # Produces string 'aaa', 'bbb', etc.
|
|
|
|
decimal = base_data[1] + i
|
|
|
|
date = base_data[2] - datetime.timedelta(days=i * 2)
|
|
|
|
FilterableItem(text=text, decimal=decimal, date=date).save()
|
|
|
|
|
|
|
|
self.objects = FilterableItem.objects
|
|
|
|
self.data = [
|
|
|
|
{'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date}
|
|
|
|
for obj in self.objects.all()
|
|
|
|
]
|
|
|
|
self.view = FilterFieldsRootView.as_view()
|
|
|
|
|
2012-11-08 01:07:24 +04:00
|
|
|
@unittest.skipUnless(django_filters, 'django-filters not installed')
|
2012-10-09 00:00:55 +04:00
|
|
|
def test_get_paginated_filtered_root_view(self):
|
|
|
|
"""
|
|
|
|
GET requests to paginated filtered ListCreateAPIView should return
|
|
|
|
paginated results. The next and previous links should preserve the
|
|
|
|
filtered parameters.
|
|
|
|
"""
|
|
|
|
request = factory.get('/?decimal=15.20')
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 15)
|
|
|
|
self.assertEquals(response.data['results'], self.data[:10])
|
|
|
|
self.assertNotEquals(response.data['next'], None)
|
|
|
|
self.assertEquals(response.data['previous'], None)
|
|
|
|
|
|
|
|
request = factory.get(response.data['next'])
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 15)
|
|
|
|
self.assertEquals(response.data['results'], self.data[10:15])
|
|
|
|
self.assertEquals(response.data['next'], None)
|
|
|
|
self.assertNotEquals(response.data['previous'], None)
|
|
|
|
|
|
|
|
request = factory.get(response.data['previous'])
|
|
|
|
response = self.view(request).render()
|
|
|
|
self.assertEquals(response.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertEquals(response.data['count'], 15)
|
|
|
|
self.assertEquals(response.data['results'], self.data[:10])
|
|
|
|
self.assertNotEquals(response.data['next'], None)
|
|
|
|
self.assertEquals(response.data['previous'], None)
|
|
|
|
|
2012-10-01 18:49:19 +04:00
|
|
|
|
|
|
|
class UnitTestPagination(TestCase):
|
|
|
|
"""
|
2012-11-15 17:35:34 +04:00
|
|
|
Unit tests for pagination of primitive objects.
|
2012-10-01 18:49:19 +04:00
|
|
|
"""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.objects = [char * 3 for char in 'abcdefghijklmnopqrstuvwxyz']
|
|
|
|
paginator = Paginator(self.objects, 10)
|
|
|
|
self.first_page = paginator.page(1)
|
|
|
|
self.last_page = paginator.page(3)
|
|
|
|
|
|
|
|
def test_native_pagination(self):
|
2012-11-05 14:53:20 +04:00
|
|
|
serializer = pagination.PaginationSerializer(self.first_page)
|
2012-10-01 18:49:19 +04:00
|
|
|
self.assertEquals(serializer.data['count'], 26)
|
|
|
|
self.assertEquals(serializer.data['next'], '?page=2')
|
|
|
|
self.assertEquals(serializer.data['previous'], None)
|
|
|
|
self.assertEquals(serializer.data['results'], self.objects[:10])
|
|
|
|
|
2012-11-05 14:53:20 +04:00
|
|
|
serializer = pagination.PaginationSerializer(self.last_page)
|
2012-10-01 18:49:19 +04:00
|
|
|
self.assertEquals(serializer.data['count'], 26)
|
|
|
|
self.assertEquals(serializer.data['next'], None)
|
|
|
|
self.assertEquals(serializer.data['previous'], '?page=2')
|
|
|
|
self.assertEquals(serializer.data['results'], self.objects[20:])
|
2012-11-15 17:35:34 +04:00
|
|
|
|
|
|
|
|
2012-11-17 02:45:57 +04:00
|
|
|
class TestUnpaginated(TestCase):
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
2012-11-17 02:45:57 +04:00
|
|
|
Tests for list views without pagination.
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
2012-11-17 02:45:57 +04:00
|
|
|
def test_unpaginated(self):
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
Tests the default page size for this view.
|
|
|
|
no page size --> no limit --> no meta data
|
|
|
|
"""
|
|
|
|
request = factory.get('/')
|
2012-11-17 02:45:57 +04:00
|
|
|
response = self.view(request)
|
2012-11-15 17:35:34 +04:00
|
|
|
self.assertEquals(response.data, self.data)
|
|
|
|
|
|
|
|
|
2012-11-17 02:45:57 +04:00
|
|
|
class TestCustomPaginateByParam(TestCase):
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
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()
|
|
|
|
]
|
2012-11-17 02:45:57 +04:00
|
|
|
self.view = PaginateByParamView.as_view()
|
2012-11-15 17:35:34 +04:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2012-11-17 02:45:57 +04:00
|
|
|
def test_paginate_by_param(self):
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
2012-11-17 02:45:57 +04:00
|
|
|
If paginate_by_param is set, the new kwarg should limit per view requests.
|
2012-11-15 17:35:34 +04:00
|
|
|
"""
|
|
|
|
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])
|