diff options
Diffstat (limited to 'rest_framework/tests/pagination.py')
| -rw-r--r-- | rest_framework/tests/pagination.py | 112 |
1 files changed, 86 insertions, 26 deletions
diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/pagination.py index 6b9970a6..e538a78e 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/pagination.py @@ -1,17 +1,24 @@ from __future__ import unicode_literals import datetime from decimal import Decimal +from django.db import models 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, filters, serializers from rest_framework.compat import django_filters -from rest_framework.tests.models import BasicModel, FilterableItem +from rest_framework.tests.models import BasicModel factory = RequestFactory() +class FilterableItem(models.Model): + text = models.CharField(max_length=100) + decimal = models.DecimalField(max_digits=4, decimal_places=2) + date = models.DateField() + + class RootView(generics.ListCreateAPIView): """ Example description for OPTIONS. @@ -20,21 +27,6 @@ class RootView(generics.ListCreateAPIView): paginate_by = 10 -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 - filter_backend = filters.DjangoFilterBackend - - class DefaultPageSizeKwargView(generics.ListAPIView): """ View for testing default paginate_by_param usage @@ -73,7 +65,9 @@ class IntegrationTestPagination(TestCase): GET requests to paginated ListCreateAPIView should return paginated results. """ request = factory.get('/') - response = self.view(request).render() + # Note: Database queries are a `SELECT COUNT`, and `SELECT <fields>` + with self.assertNumQueries(2): + response = self.view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 26) self.assertEqual(response.data['results'], self.data[:10]) @@ -81,7 +75,8 @@ class IntegrationTestPagination(TestCase): self.assertEqual(response.data['previous'], None) request = factory.get(response.data['next']) - response = self.view(request).render() + with self.assertNumQueries(2): + response = self.view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 26) self.assertEqual(response.data['results'], self.data[10:20]) @@ -89,7 +84,8 @@ class IntegrationTestPagination(TestCase): self.assertNotEqual(response.data['previous'], None) request = factory.get(response.data['next']) - response = self.view(request).render() + with self.assertNumQueries(2): + response = self.view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 26) self.assertEqual(response.data['results'], self.data[20:]) @@ -112,20 +108,37 @@ class IntegrationTestPaginationAndFiltering(TestCase): self.objects = FilterableItem.objects self.data = [ - {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date} - for obj in self.objects.all() + {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date} + for obj in self.objects.all() ] - self.view = FilterFieldsRootView.as_view() @unittest.skipUnless(django_filters, 'django-filters not installed') - def test_get_paginated_filtered_root_view(self): + def test_get_django_filter_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. """ + 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 + filter_backends = (filters.DjangoFilterBackend,) + + view = FilterFieldsRootView.as_view() + + EXPECTED_NUM_QUERIES = 2 + request = factory.get('/?decimal=15.20') - response = self.view(request).render() + with self.assertNumQueries(EXPECTED_NUM_QUERIES): + response = view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 15) self.assertEqual(response.data['results'], self.data[:10]) @@ -133,7 +146,8 @@ class IntegrationTestPaginationAndFiltering(TestCase): self.assertEqual(response.data['previous'], None) request = factory.get(response.data['next']) - response = self.view(request).render() + with self.assertNumQueries(EXPECTED_NUM_QUERIES): + response = view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 15) self.assertEqual(response.data['results'], self.data[10:15]) @@ -141,7 +155,53 @@ class IntegrationTestPaginationAndFiltering(TestCase): self.assertNotEqual(response.data['previous'], None) request = factory.get(response.data['previous']) - response = self.view(request).render() + with self.assertNumQueries(EXPECTED_NUM_QUERIES): + response = view(request).render() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 15) + self.assertEqual(response.data['results'], self.data[:10]) + self.assertNotEqual(response.data['next'], None) + self.assertEqual(response.data['previous'], None) + + def test_get_basic_paginated_filtered_root_view(self): + """ + Same as `test_get_django_filter_paginated_filtered_root_view`, + except using a custom filter backend instead of the django-filter + backend, + """ + + class DecimalFilterBackend(filters.BaseFilterBackend): + def filter_queryset(self, request, queryset, view): + return queryset.filter(decimal__lt=Decimal(request.GET['decimal'])) + + class BasicFilterFieldsRootView(generics.ListCreateAPIView): + model = FilterableItem + paginate_by = 10 + filter_backends = (DecimalFilterBackend,) + + view = BasicFilterFieldsRootView.as_view() + + request = factory.get('/?decimal=15.20') + with self.assertNumQueries(2): + response = view(request).render() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 15) + self.assertEqual(response.data['results'], self.data[:10]) + self.assertNotEqual(response.data['next'], None) + self.assertEqual(response.data['previous'], None) + + request = factory.get(response.data['next']) + with self.assertNumQueries(2): + response = view(request).render() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['count'], 15) + self.assertEqual(response.data['results'], self.data[10:15]) + self.assertEqual(response.data['next'], None) + self.assertNotEqual(response.data['previous'], None) + + request = factory.get(response.data['previous']) + with self.assertNumQueries(2): + response = view(request).render() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['count'], 15) self.assertEqual(response.data['results'], self.data[:10]) |
