Expose request to filters

This commit is contained in:
Nicolas Delaby 2016-10-11 16:16:28 +02:00
parent 5c7274c02b
commit 39c1b4e413
4 changed files with 33 additions and 4 deletions

View File

@ -277,7 +277,7 @@ FILTER_FOR_DBFIELD_DEFAULTS = {
class BaseFilterSet(object):
FILTER_DEFAULTS = FILTER_FOR_DBFIELD_DEFAULTS
def __init__(self, data=None, queryset=None, prefix=None, strict=None):
def __init__(self, data=None, queryset=None, prefix=None, strict=None, request=None):
self.is_bound = data is not None
self.data = data or {}
if queryset is None:
@ -288,6 +288,8 @@ class BaseFilterSet(object):
# What to do on on validation errors
self.strict = self._meta.strict if strict is None else strict
self.request = request
self.filters = copy.deepcopy(self.base_filters)
# propagate the model being used through the filters
for filter_ in self.filters.values():

View File

@ -71,7 +71,7 @@ class DjangoFilterBackend(BaseFilterBackend):
filter_class = self.get_filter_class(view, queryset)
if filter_class:
return filter_class(request.query_params, queryset=queryset).qs
return filter_class(request.query_params, queryset=queryset, request=request).qs
return queryset
@ -79,7 +79,7 @@ class DjangoFilterBackend(BaseFilterBackend):
filter_class = self.get_filter_class(view, queryset)
if not filter_class:
return None
filter_instance = filter_class(request.query_params, queryset=queryset)
filter_instance = filter_class(request.query_params, queryset=queryset, request=request)
try:
template = loader.get_template(self.template)

View File

@ -36,7 +36,10 @@ class FilterMixin(object):
"""
Returns the keyword arguments for instanciating the filterset.
"""
kwargs = {'data': self.request.GET or None}
kwargs = {
'data': self.request.GET or None,
'request': self.request,
}
try:
kwargs.update({
'queryset': self.get_queryset(),

View File

@ -562,6 +562,16 @@ class FilterSetInstantiationTests(TestCase):
f = F(queryset=m)
self.assertEqual(f.queryset, m)
def test_creating_with_request(self):
class F(FilterSet):
class Meta:
model = User
fields = ['username']
m = mock.Mock()
f = F(request=m)
self.assertEqual(f.request, m)
class FilterSetTogetherTests(TestCase):
@ -642,6 +652,20 @@ class FilterMethodTests(TestCase):
self.assertEqual(f.filters['f'].filter.method, filter_f)
self.assertIsInstance(f.filters['f'].filter, FilterMethod)
def test_request_available_during_method_called(self):
class F(FilterSet):
f = Filter(method='filter_f')
def filter_f(self, qs, name, value):
# call mock request object to prove self.request can be accessed
self.request()
m = mock.Mock()
f = F({}, queryset=User.objects.all(), request=m)
# call the filter
f.filters['f'].filter.method(User.objects.all(), 'f', '')
m.assert_called_once_with()
def test_method_with_overridden_filter(self):
# Some filter classes override the base filter() method. We need
# to ensure that passing a method argument still works correctly