mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-03 05:04:31 +03:00
Base automatic filterset model on the queryset model. Fixes #834.
This commit is contained in:
parent
d62414147f
commit
e939e1755a
|
@ -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
|
||||
|
|
|
@ -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'),
|
||||
)
|
||||
|
||||
|
||||
|
@ -147,6 +157,17 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
|
|||
expected_data = [f for f in self.data if f['decimal'] == search_decimal]
|
||||
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):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user