Skip to content

Commit 98df932

Browse files
spearkitomchristie
authored andcommitted
Fix FilterSet proxy (#4620)
1 parent d92b24a commit 98df932

File tree

2 files changed

+49
-9
lines changed

2 files changed

+49
-9
lines changed

rest_framework/filters.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,32 @@ def get_schema_fields(self, view):
3737
return []
3838

3939

40-
class FilterSet(object):
41-
def __new__(cls, *args, **kwargs):
42-
warnings.warn(
43-
"The built in 'rest_framework.filters.FilterSet' is pending deprecation. "
44-
"You should use 'django_filters.rest_framework.FilterSet' instead.",
45-
PendingDeprecationWarning
46-
)
47-
from django_filters.rest_framework import FilterSet
48-
return FilterSet(*args, **kwargs)
40+
if django_filters:
41+
from django_filters.filterset import FilterSetMetaclass as DFFilterSetMetaclass
42+
from django_filters.rest_framework.filterset import FilterSet as DFFilterSet
43+
44+
class FilterSetMetaclass(DFFilterSetMetaclass):
45+
def __new__(cls, name, bases, attrs):
46+
warnings.warn(
47+
"The built in 'rest_framework.filters.FilterSet' is pending deprecation. "
48+
"You should use 'django_filters.rest_framework.FilterSet' instead.",
49+
PendingDeprecationWarning
50+
)
51+
return super(FilterSetMetaclass, cls).__new__(cls, name, bases, attrs)
52+
_BaseFilterSet = DFFilterSet
53+
else:
54+
# Dummy metaclass just so we can give a user-friendly error message.
55+
class FilterSetMetaclass(type):
56+
def __init__(self, name, bases, attrs):
57+
# Assert only on subclasses, so we can define FilterSet below.
58+
if bases != (object,):
59+
assert False, 'django-filter must be installed to use the `FilterSet` class'
60+
super(FilterSetMetaclass, self).__init__(name, bases, attrs)
61+
_BaseFilterSet = object
62+
63+
64+
class FilterSet(six.with_metaclass(FilterSetMetaclass, _BaseFilterSet)):
65+
pass
4966

5067

5168
class DjangoFilterBackend(BaseFilterBackend):

tests/test_filters.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,23 @@ class Meta:
7979
model = BaseFilterableItem
8080
fields = '__all__'
8181

82+
# Test the same filter using the deprecated internal FilterSet class.
83+
class BaseFilterableItemFilterWithProxy(filters.FilterSet):
84+
text = django_filters.CharFilter()
85+
86+
class Meta:
87+
model = BaseFilterableItem
88+
fields = '__all__'
89+
8290
class BaseFilterableItemFilterRootView(generics.ListCreateAPIView):
8391
queryset = FilterableItem.objects.all()
8492
serializer_class = FilterableItemSerializer
8593
filter_class = BaseFilterableItemFilter
8694
filter_backends = (filters.DjangoFilterBackend,)
8795

96+
class BaseFilterableItemFilterWithProxyRootView(BaseFilterableItemFilterRootView):
97+
filter_class = BaseFilterableItemFilterWithProxy
98+
8899
# Regression test for #814
89100
class FilterFieldsQuerysetView(generics.ListCreateAPIView):
90101
queryset = FilterableItem.objects.all()
@@ -296,6 +307,18 @@ def test_base_model_filter(self):
296307
self.assertEqual(response.status_code, status.HTTP_200_OK)
297308
self.assertEqual(len(response.data), 1)
298309

310+
@unittest.skipUnless(django_filters, 'django-filter not installed')
311+
def test_base_model_filter_with_proxy(self):
312+
"""
313+
The `get_filter_class` model checks should allow base model filters.
314+
"""
315+
view = BaseFilterableItemFilterWithProxyRootView.as_view()
316+
317+
request = factory.get('/?text=aaa')
318+
response = view(request).render()
319+
self.assertEqual(response.status_code, status.HTTP_200_OK)
320+
self.assertEqual(len(response.data), 1)
321+
299322
@unittest.skipUnless(django_filters, 'django-filter not installed')
300323
def test_unknown_filter(self):
301324
"""

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy