diff options
| -rw-r--r-- | rest_framework/filters.py | 19 | ||||
| -rw-r--r-- | rest_framework/tests/filters.py | 21 | 
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  | 
