Skip to content

Commit

Permalink
FieldFilter cleans iterable values correctly
Browse files Browse the repository at this point in the history
Fixes #2
  • Loading branch information
bennullgraham committed Jan 12, 2017
1 parent 19185a4 commit 0113758
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
16 changes: 15 additions & 1 deletion filternaut/filters.py
Expand Up @@ -2,6 +2,10 @@

from __future__ import absolute_import, unicode_literals

from collections import Iterable

import six

from django.forms import (BooleanField, CharField, ChoiceField, ComboField,
DateField, DateTimeField, DecimalField, EmailField,
FilePathField, FloatField, ImageField, IntegerField,
Expand All @@ -25,6 +29,13 @@
'TimeFilter', 'TypedChoiceFilter', 'URLFilter']


def is_listlike(val):
"""
True if `val` is an iterable (list, tuple, ...) but not a string
"""
return isinstance(val, Iterable) and not isinstance(val, six.string_types)


class FieldFilter(Filter):
"""
FieldFilters use a django.forms.Field to clean their input value when
Expand All @@ -42,7 +53,10 @@ def __init__(self, dest, field, **kwargs):
super(FieldFilter, self).__init__(dest, **kwargs)

def clean(self, value):
return self.field.clean(value)
if is_listlike(value):
return type(value)(self.field.clean(v) for v in value)
else:
return self.field.clean(value)


# -- mixtures of fieldfilter and django fields requiring additional arguments
Expand Down
17 changes: 16 additions & 1 deletion tests/test_filters.py
Expand Up @@ -9,7 +9,8 @@
from django import VERSION as DJANGO_VERSION
from django.utils.datastructures import MultiValueDict
from filternaut import Filter, Optional
from filternaut.filters import ChoiceFilter, FilePathFilter, RegexFilter
from filternaut.filters import (CharFilter, ChoiceFilter, FilePathFilter,
RegexFilter)
from tests.util import NopeFilter, flatten_qobj


Expand Down Expand Up @@ -311,6 +312,20 @@ def test_instantiate_all_filterfields_without_special_args(self):
else:
assert not hasattr(filternaut.filters, f)

def test_listlike_values_cleaned_individually(self):
f = CharFilter('fieldname', lookups='exact,in')
data = MultiValueDict({
'fieldname': ['single value'], # MVDict treats 1-list as single
'fieldname__in': ['multiple', 'values'],
})
expected = {
'fieldname': 'single value',
'fieldname__in': ['multiple', 'values']
}
f.parse(data)
actual = dict(flatten_qobj(f.Q))
assert expected == actual


class DefaultValueTests(TestCase):

Expand Down

0 comments on commit 0113758

Please sign in to comment.