mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 13:14:30 +03:00
Remove DjangoFilterBackend and associated tests
This commit is contained in:
parent
cb6e7e0fdd
commit
f6c19e5eac
|
@ -182,13 +182,6 @@ except ImportError:
|
||||||
coreschema = None
|
coreschema = None
|
||||||
|
|
||||||
|
|
||||||
# django-filter is optional
|
|
||||||
try:
|
|
||||||
import django_filters
|
|
||||||
except ImportError:
|
|
||||||
django_filters = None
|
|
||||||
|
|
||||||
|
|
||||||
# django-crispy-forms is optional
|
# django-crispy-forms is optional
|
||||||
try:
|
try:
|
||||||
import crispy_forms
|
import crispy_forms
|
||||||
|
|
|
@ -5,7 +5,6 @@ returned by list views.
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import operator
|
import operator
|
||||||
import warnings
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
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 django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from rest_framework.compat import (
|
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
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
@ -40,44 +39,6 @@ class BaseFilterBackend(object):
|
||||||
return []
|
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):
|
class SearchFilter(BaseFilterBackend):
|
||||||
# The URL query parameter used for the search.
|
# The URL query parameter used for the search.
|
||||||
search_param = api_settings.SEARCH_PARAM
|
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
|
# Models for relations tests
|
||||||
# ManyToMany
|
# ManyToMany
|
||||||
class ManyToManyTarget(RESTFrameworkModel):
|
class ManyToManyTarget(RESTFrameworkModel):
|
||||||
|
|
|
@ -2,125 +2,21 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import unittest
|
import unittest
|
||||||
import warnings
|
|
||||||
from decimal import Decimal
|
|
||||||
|
|
||||||
import django
|
import django
|
||||||
import pytest
|
import pytest
|
||||||
from django.conf.urls import url
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.utils.dateparse import parse_date
|
|
||||||
from django.utils.six.moves import reload_module
|
from django.utils.six.moves import reload_module
|
||||||
|
|
||||||
from rest_framework import filters, generics, serializers, status
|
from rest_framework import filters, generics, serializers
|
||||||
from rest_framework.compat import django_filters, reverse
|
|
||||||
from rest_framework.test import APIRequestFactory
|
from rest_framework.test import APIRequestFactory
|
||||||
|
|
||||||
from .models import BaseFilterableItem, BasicModel, FilterableItem
|
|
||||||
|
|
||||||
factory = APIRequestFactory()
|
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):
|
class BaseFilterTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.original_coreapi = filters.coreapi
|
self.original_coreapi = filters.coreapi
|
||||||
|
@ -142,288 +38,6 @@ class BaseFilterTests(TestCase):
|
||||||
assert self.filter_backend.get_schema_fields({}) == []
|
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):
|
class SearchFilterModel(models.Model):
|
||||||
title = models.CharField(max_length=20)
|
title = models.CharField(max_length=20)
|
||||||
text = models.CharField(max_length=100)
|
text = models.CharField(max_length=100)
|
||||||
|
@ -720,42 +334,6 @@ class DjangoFilterOrderingSerializer(serializers.ModelSerializer):
|
||||||
fields = '__all__'
|
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):
|
class OrderingFilterTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Sequence of title/text is:
|
# Sequence of title/text is:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user