mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 18:08:03 +03:00 
			
		
		
		
	Remove DjangoFilterBackend and associated tests
This commit is contained in:
		
							parent
							
								
									cb6e7e0fdd
								
							
						
					
					
						commit
						f6c19e5eac
					
				| 
						 | 
				
			
			@ -182,13 +182,6 @@ except ImportError:
 | 
			
		|||
    coreschema = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# django-filter is optional
 | 
			
		||||
try:
 | 
			
		||||
    import django_filters
 | 
			
		||||
except ImportError:
 | 
			
		||||
    django_filters = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# django-crispy-forms is optional
 | 
			
		||||
try:
 | 
			
		||||
    import crispy_forms
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@ returned by list views.
 | 
			
		|||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import operator
 | 
			
		||||
import warnings
 | 
			
		||||
from functools import reduce
 | 
			
		||||
 | 
			
		||||
from django.core.exceptions import ImproperlyConfigured
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +17,7 @@ from django.utils.encoding import force_text
 | 
			
		|||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from rest_framework.compat import (
 | 
			
		||||
    coreapi, coreschema, distinct, django_filters, guardian, template_render
 | 
			
		||||
    coreapi, coreschema, distinct, guardian, template_render
 | 
			
		||||
)
 | 
			
		||||
from rest_framework.settings import api_settings
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,44 +39,6 @@ class BaseFilterBackend(object):
 | 
			
		|||
        return []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if django_filters:
 | 
			
		||||
    from django_filters.rest_framework.filterset import FilterSet as DFFilterSet
 | 
			
		||||
 | 
			
		||||
    class FilterSet(DFFilterSet):
 | 
			
		||||
        def __init__(self, *args, **kwargs):
 | 
			
		||||
            warnings.warn(
 | 
			
		||||
                "The built in 'rest_framework.filters.FilterSet' is deprecated. "
 | 
			
		||||
                "You should use 'django_filters.rest_framework.FilterSet' instead.",
 | 
			
		||||
                DeprecationWarning, stacklevel=2
 | 
			
		||||
            )
 | 
			
		||||
            return super(FilterSet, self).__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    DFBase = django_filters.rest_framework.DjangoFilterBackend
 | 
			
		||||
 | 
			
		||||
else:
 | 
			
		||||
    def FilterSet():
 | 
			
		||||
        assert False, 'django-filter must be installed to use the `FilterSet` class'
 | 
			
		||||
 | 
			
		||||
    DFBase = BaseFilterBackend
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DjangoFilterBackend(DFBase):
 | 
			
		||||
    """
 | 
			
		||||
    A filter backend that uses django-filter.
 | 
			
		||||
    """
 | 
			
		||||
    def __new__(cls, *args, **kwargs):
 | 
			
		||||
        assert django_filters, 'Using DjangoFilterBackend, but django-filter is not installed'
 | 
			
		||||
        assert django_filters.VERSION >= (0, 15, 3), 'django-filter 0.15.3 and above is required'
 | 
			
		||||
 | 
			
		||||
        warnings.warn(
 | 
			
		||||
            "The built in 'rest_framework.filters.DjangoFilterBackend' is deprecated. "
 | 
			
		||||
            "You should use 'django_filters.rest_framework.DjangoFilterBackend' instead.",
 | 
			
		||||
            DeprecationWarning, stacklevel=2
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        return super(DjangoFilterBackend, cls).__new__(cls, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SearchFilter(BaseFilterBackend):
 | 
			
		||||
    # The URL query parameter used for the search.
 | 
			
		||||
    search_param = api_settings.SEARCH_PARAM
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,15 +24,6 @@ class BasicModel(RESTFrameworkModel):
 | 
			
		|||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseFilterableItem(RESTFrameworkModel):
 | 
			
		||||
    text = models.CharField(max_length=100)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FilterableItem(BaseFilterableItem):
 | 
			
		||||
    decimal = models.DecimalField(max_digits=4, decimal_places=2)
 | 
			
		||||
    date = models.DateField()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Models for relations tests
 | 
			
		||||
# ManyToMany
 | 
			
		||||
class ManyToManyTarget(RESTFrameworkModel):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,125 +2,21 @@ from __future__ import unicode_literals
 | 
			
		|||
 | 
			
		||||
import datetime
 | 
			
		||||
import unittest
 | 
			
		||||
import warnings
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
 | 
			
		||||
import django
 | 
			
		||||
import pytest
 | 
			
		||||
from django.conf.urls import url
 | 
			
		||||
from django.core.exceptions import ImproperlyConfigured
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
from django.test.utils import override_settings
 | 
			
		||||
from django.utils.dateparse import parse_date
 | 
			
		||||
from django.utils.six.moves import reload_module
 | 
			
		||||
 | 
			
		||||
from rest_framework import filters, generics, serializers, status
 | 
			
		||||
from rest_framework.compat import django_filters, reverse
 | 
			
		||||
from rest_framework import filters, generics, serializers
 | 
			
		||||
from rest_framework.test import APIRequestFactory
 | 
			
		||||
 | 
			
		||||
from .models import BaseFilterableItem, BasicModel, FilterableItem
 | 
			
		||||
 | 
			
		||||
factory = APIRequestFactory()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if django_filters:
 | 
			
		||||
    class FilterableItemSerializer(serializers.ModelSerializer):
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = FilterableItem
 | 
			
		||||
            fields = '__all__'
 | 
			
		||||
 | 
			
		||||
    # Basic filter on a list view.
 | 
			
		||||
    class FilterFieldsRootView(generics.ListCreateAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_fields = ['decimal', 'date']
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    # These class are used to test a filter class.
 | 
			
		||||
    class SeveralFieldsFilter(django_filters.FilterSet):
 | 
			
		||||
        text = django_filters.CharFilter(lookup_expr='icontains')
 | 
			
		||||
        decimal = django_filters.NumberFilter(lookup_expr='lt')
 | 
			
		||||
        date = django_filters.DateFilter(lookup_expr='gt')
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = FilterableItem
 | 
			
		||||
            fields = ['text', 'decimal', 'date']
 | 
			
		||||
 | 
			
		||||
    class FilterClassRootView(generics.ListCreateAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_class = SeveralFieldsFilter
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    # These classes are used to test a misconfigured filter class.
 | 
			
		||||
    class MisconfiguredFilter(django_filters.FilterSet):
 | 
			
		||||
        text = django_filters.CharFilter(lookup_expr='icontains')
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = BasicModel
 | 
			
		||||
            fields = ['text']
 | 
			
		||||
 | 
			
		||||
    class IncorrectlyConfiguredRootView(generics.ListCreateAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_class = MisconfiguredFilter
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    class FilterClassDetailView(generics.RetrieveAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_class = SeveralFieldsFilter
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    # These classes are used to test base model filter support
 | 
			
		||||
    class BaseFilterableItemFilter(django_filters.FilterSet):
 | 
			
		||||
        text = django_filters.CharFilter()
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = BaseFilterableItem
 | 
			
		||||
            fields = '__all__'
 | 
			
		||||
 | 
			
		||||
    # Test the same filter using the deprecated internal FilterSet class.
 | 
			
		||||
    class BaseFilterableItemFilterWithProxy(filters.FilterSet):
 | 
			
		||||
        text = django_filters.CharFilter()
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = BaseFilterableItem
 | 
			
		||||
            fields = '__all__'
 | 
			
		||||
 | 
			
		||||
    class BaseFilterableItemFilterRootView(generics.ListCreateAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_class = BaseFilterableItemFilter
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    class BaseFilterableItemFilterWithProxyRootView(BaseFilterableItemFilterRootView):
 | 
			
		||||
        filter_class = BaseFilterableItemFilterWithProxy
 | 
			
		||||
 | 
			
		||||
    # Regression test for #814
 | 
			
		||||
    class FilterFieldsQuerysetView(generics.ListCreateAPIView):
 | 
			
		||||
        queryset = FilterableItem.objects.all()
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_fields = ['decimal', 'date']
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
    class GetQuerysetView(generics.ListCreateAPIView):
 | 
			
		||||
        serializer_class = FilterableItemSerializer
 | 
			
		||||
        filter_class = SeveralFieldsFilter
 | 
			
		||||
        filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
        def get_queryset(self):
 | 
			
		||||
            return FilterableItem.objects.all()
 | 
			
		||||
 | 
			
		||||
    urlpatterns = [
 | 
			
		||||
        url(r'^(?P<pk>\d+)/$', FilterClassDetailView.as_view(), name='detail-view'),
 | 
			
		||||
        url(r'^$', FilterClassRootView.as_view(), name='root-view'),
 | 
			
		||||
        url(r'^get-queryset/$', GetQuerysetView.as_view(),
 | 
			
		||||
            name='get-queryset-view'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseFilterTests(TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.original_coreapi = filters.coreapi
 | 
			
		||||
| 
						 | 
				
			
			@ -142,288 +38,6 @@ class BaseFilterTests(TestCase):
 | 
			
		|||
        assert self.filter_backend.get_schema_fields({}) == []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CommonFilteringTestCase(TestCase):
 | 
			
		||||
    def _serialize_object(self, obj):
 | 
			
		||||
        return {'id': obj.id, 'text': obj.text, 'decimal': str(obj.decimal), 'date': obj.date.isoformat()}
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        """
 | 
			
		||||
        Create 10 FilterableItem instances.
 | 
			
		||||
        """
 | 
			
		||||
        base_data = ('a', Decimal('0.25'), datetime.date(2012, 10, 8))
 | 
			
		||||
        for i in range(10):
 | 
			
		||||
            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 = [
 | 
			
		||||
            self._serialize_object(obj)
 | 
			
		||||
            for obj in self.objects.all()
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IntegrationTestFiltering(CommonFilteringTestCase):
 | 
			
		||||
    """
 | 
			
		||||
    Integration tests for filtered list views.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_backend_deprecation(self):
 | 
			
		||||
        with warnings.catch_warnings(record=True) as w:
 | 
			
		||||
            warnings.simplefilter("always")
 | 
			
		||||
 | 
			
		||||
            view = FilterFieldsRootView.as_view()
 | 
			
		||||
            request = factory.get('/')
 | 
			
		||||
            response = view(request).render()
 | 
			
		||||
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == self.data
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
 | 
			
		||||
        self.assertIn("'rest_framework.filters.DjangoFilterBackend' is deprecated.", str(w[-1].message))
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_no_df_deprecation(self):
 | 
			
		||||
        with warnings.catch_warnings(record=True) as w:
 | 
			
		||||
            warnings.simplefilter("always")
 | 
			
		||||
 | 
			
		||||
            import django_filters.rest_framework
 | 
			
		||||
 | 
			
		||||
            class DFFilterFieldsRootView(FilterFieldsRootView):
 | 
			
		||||
                filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
 | 
			
		||||
 | 
			
		||||
            view = DFFilterFieldsRootView.as_view()
 | 
			
		||||
            request = factory.get('/')
 | 
			
		||||
            response = view(request).render()
 | 
			
		||||
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == self.data
 | 
			
		||||
        assert len(w) == 0
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_backend_mro(self):
 | 
			
		||||
        class CustomBackend(filters.DjangoFilterBackend):
 | 
			
		||||
            def filter_queryset(self, request, queryset, view):
 | 
			
		||||
                assert False, "custom filter_queryset should run"
 | 
			
		||||
 | 
			
		||||
        class DFFilterFieldsRootView(FilterFieldsRootView):
 | 
			
		||||
            filter_backends = (CustomBackend,)
 | 
			
		||||
 | 
			
		||||
        view = DFFilterFieldsRootView.as_view()
 | 
			
		||||
        request = factory.get('/')
 | 
			
		||||
 | 
			
		||||
        with pytest.raises(AssertionError, message="custom filter_queryset should run"):
 | 
			
		||||
            view(request).render()
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_get_filtered_fields_root_view(self):
 | 
			
		||||
        """
 | 
			
		||||
        GET requests to paginated ListCreateAPIView should return paginated results.
 | 
			
		||||
        """
 | 
			
		||||
        view = FilterFieldsRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        # Basic test with no filter.
 | 
			
		||||
        request = factory.get('/')
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == self.data
 | 
			
		||||
 | 
			
		||||
        # Tests that the decimal filter works.
 | 
			
		||||
        search_decimal = Decimal('2.25')
 | 
			
		||||
        request = factory.get('/', {'decimal': '%s' % search_decimal})
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
        # Tests that the date filter works.
 | 
			
		||||
        search_date = datetime.date(2012, 9, 22)
 | 
			
		||||
        request = factory.get('/', {'date': '%s' % search_date})  # search_date str: '2012-09-22'
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if parse_date(f['date']) == search_date]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_filter_with_queryset(self):
 | 
			
		||||
        """
 | 
			
		||||
        Regression test for #814.
 | 
			
		||||
        """
 | 
			
		||||
        view = FilterFieldsQuerysetView.as_view()
 | 
			
		||||
 | 
			
		||||
        # Tests that the decimal filter works.
 | 
			
		||||
        search_decimal = Decimal('2.25')
 | 
			
		||||
        request = factory.get('/', {'decimal': '%s' % search_decimal})
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if Decimal(f['decimal']) == search_decimal]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_filter_with_get_queryset_only(self):
 | 
			
		||||
        """
 | 
			
		||||
        Regression test for #834.
 | 
			
		||||
        """
 | 
			
		||||
        view = GetQuerysetView.as_view()
 | 
			
		||||
        request = factory.get('/get-queryset/')
 | 
			
		||||
        view(request).render()
 | 
			
		||||
        # Used to raise "issubclass() arg 2 must be a class or tuple of classes"
 | 
			
		||||
        # here when neither `model' nor `queryset' was specified.
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_get_filtered_class_root_view(self):
 | 
			
		||||
        """
 | 
			
		||||
        GET requests to filtered ListCreateAPIView that have a filter_class set
 | 
			
		||||
        should return filtered results.
 | 
			
		||||
        """
 | 
			
		||||
        view = FilterClassRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        # Basic test with no filter.
 | 
			
		||||
        request = factory.get('/')
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == self.data
 | 
			
		||||
 | 
			
		||||
        # Tests that the decimal filter set with 'lt' in the filter class works.
 | 
			
		||||
        search_decimal = Decimal('4.25')
 | 
			
		||||
        request = factory.get('/', {'decimal': '%s' % search_decimal})
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if Decimal(f['decimal']) < search_decimal]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
        # Tests that the date filter set with 'gt' in the filter class works.
 | 
			
		||||
        search_date = datetime.date(2012, 10, 2)
 | 
			
		||||
        request = factory.get('/', {'date': '%s' % search_date})  # search_date str: '2012-10-02'
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if parse_date(f['date']) > search_date]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
        # Tests that the text filter set with 'icontains' in the filter class works.
 | 
			
		||||
        search_text = 'ff'
 | 
			
		||||
        request = factory.get('/', {'text': '%s' % search_text})
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if search_text in f['text'].lower()]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
        # Tests that multiple filters works.
 | 
			
		||||
        search_decimal = Decimal('5.25')
 | 
			
		||||
        search_date = datetime.date(2012, 10, 2)
 | 
			
		||||
        request = factory.get('/', {
 | 
			
		||||
            'decimal': '%s' % (search_decimal,),
 | 
			
		||||
            'date': '%s' % (search_date,)
 | 
			
		||||
        })
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        expected_data = [f for f in self.data if parse_date(f['date']) > search_date and
 | 
			
		||||
                         Decimal(f['decimal']) < search_decimal]
 | 
			
		||||
        assert response.data == expected_data
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_incorrectly_configured_filter(self):
 | 
			
		||||
        """
 | 
			
		||||
        An error should be displayed when the filter class is misconfigured.
 | 
			
		||||
        """
 | 
			
		||||
        view = IncorrectlyConfiguredRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/')
 | 
			
		||||
        self.assertRaises(AssertionError, view, request)
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_base_model_filter(self):
 | 
			
		||||
        """
 | 
			
		||||
        The `get_filter_class` model checks should allow base model filters.
 | 
			
		||||
        """
 | 
			
		||||
        view = BaseFilterableItemFilterRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/?text=aaa')
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert len(response.data) == 1
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_base_model_filter_with_proxy(self):
 | 
			
		||||
        """
 | 
			
		||||
        The `get_filter_class` model checks should allow base model filters.
 | 
			
		||||
        """
 | 
			
		||||
        view = BaseFilterableItemFilterWithProxyRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        request = factory.get('/?text=aaa')
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert len(response.data) == 1
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_unknown_filter(self):
 | 
			
		||||
        """
 | 
			
		||||
        GET requests with filters that aren't configured should return 200.
 | 
			
		||||
        """
 | 
			
		||||
        view = FilterFieldsRootView.as_view()
 | 
			
		||||
 | 
			
		||||
        search_integer = 10
 | 
			
		||||
        request = factory.get('/', {'integer': '%s' % search_integer})
 | 
			
		||||
        response = view(request).render()
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@override_settings(ROOT_URLCONF='tests.test_filters')
 | 
			
		||||
class IntegrationTestDetailFiltering(CommonFilteringTestCase):
 | 
			
		||||
    """
 | 
			
		||||
    Integration tests for filtered detail views.
 | 
			
		||||
    """
 | 
			
		||||
    def _get_url(self, item):
 | 
			
		||||
        return reverse('detail-view', kwargs=dict(pk=item.pk))
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_get_filtered_detail_view(self):
 | 
			
		||||
        """
 | 
			
		||||
        GET requests to filtered RetrieveAPIView that have a filter_class set
 | 
			
		||||
        should return filtered results.
 | 
			
		||||
        """
 | 
			
		||||
        item = self.objects.all()[0]
 | 
			
		||||
        data = self._serialize_object(item)
 | 
			
		||||
 | 
			
		||||
        # Basic test with no filter.
 | 
			
		||||
        response = self.client.get(self._get_url(item))
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == data
 | 
			
		||||
 | 
			
		||||
        # Tests that the decimal filter set that should fail.
 | 
			
		||||
        search_decimal = Decimal('4.25')
 | 
			
		||||
        high_item = self.objects.filter(decimal__gt=search_decimal)[0]
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            '{url}'.format(url=self._get_url(high_item)),
 | 
			
		||||
            {'decimal': '{param}'.format(param=search_decimal)})
 | 
			
		||||
        assert response.status_code == status.HTTP_404_NOT_FOUND
 | 
			
		||||
 | 
			
		||||
        # Tests that the decimal filter set that should succeed.
 | 
			
		||||
        search_decimal = Decimal('4.25')
 | 
			
		||||
        low_item = self.objects.filter(decimal__lt=search_decimal)[0]
 | 
			
		||||
        low_item_data = self._serialize_object(low_item)
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            '{url}'.format(url=self._get_url(low_item)),
 | 
			
		||||
            {'decimal': '{param}'.format(param=search_decimal)})
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == low_item_data
 | 
			
		||||
 | 
			
		||||
        # Tests that multiple filters works.
 | 
			
		||||
        search_decimal = Decimal('5.25')
 | 
			
		||||
        search_date = datetime.date(2012, 10, 2)
 | 
			
		||||
        valid_item = self.objects.filter(decimal__lt=search_decimal, date__gt=search_date)[0]
 | 
			
		||||
        valid_item_data = self._serialize_object(valid_item)
 | 
			
		||||
        response = self.client.get(
 | 
			
		||||
            '{url}'.format(url=self._get_url(valid_item)), {
 | 
			
		||||
                'decimal': '{decimal}'.format(decimal=search_decimal),
 | 
			
		||||
                'date': '{date}'.format(date=search_date)
 | 
			
		||||
            })
 | 
			
		||||
        assert response.status_code == status.HTTP_200_OK
 | 
			
		||||
        assert response.data == valid_item_data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SearchFilterModel(models.Model):
 | 
			
		||||
    title = models.CharField(max_length=20)
 | 
			
		||||
    text = models.CharField(max_length=100)
 | 
			
		||||
| 
						 | 
				
			
			@ -720,42 +334,6 @@ class DjangoFilterOrderingSerializer(serializers.ModelSerializer):
 | 
			
		|||
        fields = '__all__'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DjangoFilterOrderingTests(TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        data = [{
 | 
			
		||||
            'date': datetime.date(2012, 10, 8),
 | 
			
		||||
            'text': 'abc'
 | 
			
		||||
        }, {
 | 
			
		||||
            'date': datetime.date(2013, 10, 8),
 | 
			
		||||
            'text': 'bcd'
 | 
			
		||||
        }, {
 | 
			
		||||
            'date': datetime.date(2014, 10, 8),
 | 
			
		||||
            'text': 'cde'
 | 
			
		||||
        }]
 | 
			
		||||
 | 
			
		||||
        for d in data:
 | 
			
		||||
            DjangoFilterOrderingModel.objects.create(**d)
 | 
			
		||||
 | 
			
		||||
    @unittest.skipUnless(django_filters, 'django-filter not installed')
 | 
			
		||||
    def test_default_ordering(self):
 | 
			
		||||
        class DjangoFilterOrderingView(generics.ListAPIView):
 | 
			
		||||
            serializer_class = DjangoFilterOrderingSerializer
 | 
			
		||||
            queryset = DjangoFilterOrderingModel.objects.all()
 | 
			
		||||
            filter_backends = (filters.DjangoFilterBackend,)
 | 
			
		||||
            filter_fields = ['text']
 | 
			
		||||
            ordering = ('-date',)
 | 
			
		||||
 | 
			
		||||
        view = DjangoFilterOrderingView.as_view()
 | 
			
		||||
        request = factory.get('/')
 | 
			
		||||
        response = view(request)
 | 
			
		||||
 | 
			
		||||
        assert response.data == [
 | 
			
		||||
            {'id': 3, 'date': '2014-10-08', 'text': 'cde'},
 | 
			
		||||
            {'id': 2, 'date': '2013-10-08', 'text': 'bcd'},
 | 
			
		||||
            {'id': 1, 'date': '2012-10-08', 'text': 'abc'}
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OrderingFilterTests(TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        # Sequence of title/text is:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user