From 1e9ece0f9353515265da9b6266dc4b39775a0257 Mon Sep 17 00:00:00 2001 From: Ben Konrath Date: Mon, 8 Oct 2012 22:00:55 +0200 Subject: First attempt at adding filter support. The filter support uses django-filter to work its magic. --- rest_framework/tests/pagination.py | 69 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index a939c9ef..729bbfc2 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -1,8 +1,10 @@ +import datetime from django.core.paginator import Paginator from django.test import TestCase from django.test.client import RequestFactory from rest_framework import generics, status, pagination -from rest_framework.tests.models import BasicModel +from rest_framework.tests.models import BasicModel, FilterableItem +import django_filters factory = RequestFactory() @@ -15,6 +17,19 @@ class RootView(generics.ListCreateAPIView): paginate_by = 10 +class DecimalFilter(django_filters.FilterSet): + decimal = django_filters.NumberFilter(lookup_type='lt') + class Meta: + model = FilterableItem + fields = ['text', 'decimal', 'date'] + + +class FilterFieldsRootView(generics.ListCreateAPIView): + model = FilterableItem + paginate_by = 10 + filter_class = DecimalFilter + + class IntegrationTestPagination(TestCase): """ Integration tests for paginated list views. @@ -22,7 +37,7 @@ class IntegrationTestPagination(TestCase): def setUp(self): """ - Create 26 BasicModel intances. + Create 26 BasicModel instances. """ for char in 'abcdefghijklmnopqrstuvwxyz': BasicModel(text=char * 3).save() @@ -61,6 +76,56 @@ class IntegrationTestPagination(TestCase): self.assertEquals(response.data['next'], None) self.assertNotEquals(response.data['previous'], None) +class IntegrationTestPaginationAndFiltering(TestCase): + + def setUp(self): + """ + Create 50 FilterableItem instances. + """ + base_data = ('a', 0.25, datetime.date(2012, 10, 8)) + 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() + + 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) + class UnitTestPagination(TestCase): """ -- cgit v1.2.3 From e295f616ec2cfee9c24b22d4be1a605a93d9544d Mon Sep 17 00:00:00 2001 From: Ben Konrath Date: Thu, 11 Oct 2012 11:32:51 +0200 Subject: Fix small PEP8 problem. --- rest_framework/tests/pagination.py | 1 + 1 file changed, 1 insertion(+) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 729bbfc2..054b7ee3 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -76,6 +76,7 @@ class IntegrationTestPagination(TestCase): self.assertEquals(response.data['next'], None) self.assertNotEquals(response.data['previous'], None) + class IntegrationTestPaginationAndFiltering(TestCase): def setUp(self): -- cgit v1.2.3 From 6f736a682369e003e4ae4b8d587f9168d4196986 Mon Sep 17 00:00:00 2001 From: Ben Konrath Date: Thu, 11 Oct 2012 13:55:16 +0200 Subject: Explicitly use Decimal for creating filter test data. This fixes a Travis build failures on python 2.6: https://travis-ci.org/#!/tomchristie/django-rest-framework/builds/2746628 --- rest_framework/tests/pagination.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 054b7ee3..8c5e6ad7 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -1,4 +1,5 @@ import datetime +from decimal import Decimal from django.core.paginator import Paginator from django.test import TestCase from django.test.client import RequestFactory @@ -83,7 +84,7 @@ class IntegrationTestPaginationAndFiltering(TestCase): """ Create 50 FilterableItem instances. """ - base_data = ('a', 0.25, datetime.date(2012, 10, 8)) + base_data = ('a', Decimal(0.25), datetime.date(2012, 10, 8)) for i in range(26): text = chr(i + ord(base_data[0])) * 3 # Produces string 'aaa', 'bbb', etc. decimal = base_data[1] + i -- cgit v1.2.3 From 1d054f95725e5bec7d4ba9d23717897ef80b7388 Mon Sep 17 00:00:00 2001 From: Ben Konrath Date: Thu, 11 Oct 2012 14:19:29 +0200 Subject: Use Decimal (properly) everywhere. --- rest_framework/tests/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 8c5e6ad7..170515a7 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -84,7 +84,7 @@ class IntegrationTestPaginationAndFiltering(TestCase): """ Create 50 FilterableItem instances. """ - base_data = ('a', Decimal(0.25), datetime.date(2012, 10, 8)) + base_data = ('a', Decimal('0.25'), datetime.date(2012, 10, 8)) for i in range(26): text = chr(i + ord(base_data[0])) * 3 # Produces string 'aaa', 'bbb', etc. decimal = base_data[1] + i -- cgit v1.2.3 From b7b942c5991e677e7df621c00befb075d06edd61 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 5 Nov 2012 10:53:20 +0000 Subject: Swap position of `instance` and `data` keyword arguments. --- rest_framework/tests/pagination.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index a939c9ef..64e8d822 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -74,13 +74,13 @@ class UnitTestPagination(TestCase): self.last_page = paginator.page(3) def test_native_pagination(self): - serializer = pagination.PaginationSerializer(instance=self.first_page) + serializer = pagination.PaginationSerializer(self.first_page) 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]) - serializer = pagination.PaginationSerializer(instance=self.last_page) + serializer = pagination.PaginationSerializer(self.last_page) self.assertEquals(serializer.data['count'], 26) self.assertEquals(serializer.data['next'], None) self.assertEquals(serializer.data['previous'], '?page=2') -- cgit v1.2.3 From 47b534a13e42d498629bf9522225633122c563d5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 7 Nov 2012 21:07:24 +0000 Subject: Make filtering optional, and pluggable. --- rest_framework/tests/pagination.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 7a2134e0..7f8cd524 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -3,9 +3,10 @@ from decimal import Decimal from django.core.paginator import Paginator from django.test import TestCase from django.test.client import RequestFactory +from django.utils import unittest from rest_framework import generics, status, pagination +from rest_framework.compat import django_filters from rest_framework.tests.models import BasicModel, FilterableItem -import django_filters factory = RequestFactory() @@ -18,17 +19,18 @@ class RootView(generics.ListCreateAPIView): paginate_by = 10 -class DecimalFilter(django_filters.FilterSet): - decimal = django_filters.NumberFilter(lookup_type='lt') - class Meta: - model = FilterableItem - fields = ['text', 'decimal', 'date'] +if django_filters: + class DecimalFilter(django_filters.FilterSet): + decimal = django_filters.NumberFilter(lookup_type='lt') + class Meta: + model = FilterableItem + fields = ['text', 'decimal', 'date'] -class FilterFieldsRootView(generics.ListCreateAPIView): - model = FilterableItem - paginate_by = 10 - filter_class = DecimalFilter + class FilterFieldsRootView(generics.ListCreateAPIView): + model = FilterableItem + paginate_by = 10 + filter_class = DecimalFilter class IntegrationTestPagination(TestCase): @@ -98,6 +100,7 @@ class IntegrationTestPaginationAndFiltering(TestCase): ] self.view = FilterFieldsRootView.as_view() + @unittest.skipUnless(django_filters, 'django-filters not installed') def test_get_paginated_filtered_root_view(self): """ GET requests to paginated filtered ListCreateAPIView should return -- cgit v1.2.3 From bc6f2a170306fbc1cba3a4e504a908ebc72d54b7 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Nov 2012 21:46:53 +0000 Subject: Make default FILTER_BACKEND = None --- rest_framework/tests/pagination.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'rest_framework/tests/pagination.py') diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 7f8cd524..713a7255 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -4,7 +4,7 @@ from django.core.paginator import Paginator from django.test import TestCase from django.test.client import RequestFactory from django.utils import unittest -from rest_framework import generics, status, pagination +from rest_framework import generics, status, pagination, filters from rest_framework.compat import django_filters from rest_framework.tests.models import BasicModel, FilterableItem @@ -31,6 +31,7 @@ if django_filters: model = FilterableItem paginate_by = 10 filter_class = DecimalFilter + filter_backend = filters.DjangoFilterBackend class IntegrationTestPagination(TestCase): -- cgit v1.2.3