aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2013-05-14 21:40:55 +0100
committerTom Christie2013-05-14 21:40:55 +0100
commite939e1755a94b50c87a82c0f777645e28fe91bf0 (patch)
tree31430086b910aa04926477a4ac6b3754e9d6e359
parentd62414147fa949af4db698afedae7b5506229a9f (diff)
downloaddjango-rest-framework-e939e1755a94b50c87a82c0f777645e28fe91bf0.tar.bz2
Base automatic filterset model on the queryset model. Fixes #834.
-rw-r--r--rest_framework/filters.py19
-rw-r--r--rest_framework/tests/filters.py21
2 files changed, 27 insertions, 13 deletions
diff --git a/rest_framework/filters.py b/rest_framework/filters.py
index 6a3e055d..34831dd7 100644
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -32,40 +32,33 @@ class DjangoFilterBackend(BaseFilterBackend):
def __init__(self):
assert django_filters, 'Using DjangoFilterBackend, but django-filter is not installed'
- def get_filter_class(self, view):
+ def get_filter_class(self, view, queryset=None):
"""
Return the django-filters `FilterSet` used to filter the queryset.
"""
filter_class = getattr(view, 'filter_class', None)
filter_fields = getattr(view, 'filter_fields', None)
- model_cls = getattr(view, 'model', None)
- queryset = getattr(view, 'queryset', None)
- if model_cls is None and queryset is not None:
- model_cls = queryset.model
if filter_class:
filter_model = filter_class.Meta.model
- assert issubclass(filter_model, model_cls), \
- 'FilterSet model %s does not match view model %s' % \
- (filter_model, model_cls)
+ assert issubclass(filter_model, queryset.model), \
+ 'FilterSet model %s does not match queryset model %s' % \
+ (filter_model, queryset.model)
return filter_class
if filter_fields:
- assert model_cls is not None, 'Cannot use DjangoFilterBackend ' \
- 'on a view which does not have a .model or .queryset attribute.'
-
class AutoFilterSet(self.default_filter_set):
class Meta:
- model = model_cls
+ model = queryset.model
fields = filter_fields
return AutoFilterSet
return None
def filter_queryset(self, request, queryset, view):
- filter_class = self.get_filter_class(view)
+ filter_class = self.get_filter_class(view, queryset)
if filter_class:
return filter_class(request.QUERY_PARAMS, queryset=queryset).qs
diff --git a/rest_framework/tests/filters.py b/rest_framework/tests/filters.py
index 18972c84..a58c66ae 100644
--- a/rest_framework/tests/filters.py
+++ b/rest_framework/tests/filters.py
@@ -70,9 +70,19 @@ if django_filters:
filter_fields = ['decimal', 'date']
filter_backend = filters.DjangoFilterBackend
+ class GetQuerysetView(generics.ListCreateAPIView):
+ serializer_class = FilterableItemSerializer
+ filter_class = SeveralFieldsFilter
+ filter_backend = filters.DjangoFilterBackend
+
+ def get_queryset(self):
+ return FilterableItem.objects.all()
+
urlpatterns = patterns('',
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'),
)
@@ -148,6 +158,17 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
self.assertEqual(response.data, expected_data)
@unittest.skipUnless(django_filters, 'django-filters 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-filters not installed')
def test_get_filtered_class_root_view(self):
"""
GET requests to filtered ListCreateAPIView that have a filter_class set