Django-filter: CharFilter(widget=CSVWidget) no longer works in 1.x

Created on 24 May 2017  ·  3Comments  ·  Source: carltongibson/django-filter

I was using CSVWidget with a CharFilter in the pre 1.x days, but I'm upgrading and that combination no longer works. I can't find any docs or recommendations on what to switch to. I want to accept a single value or multiple values separated by commas

Most helpful comment

CSVWidget is correctly returning a list of values, however CharField.clean() is coercing the list back into a text value, hence "['1', '2', '3']". It's not sufficient to pass CSVWidget to the filter - the form field needs to be overridden to accept a list of values.

The easiest way to get the correct field behavior is to mixin the BaseCSVFilter, as it properly constructs a form field that accepts a list of values.

All 3 comments

Try something like:

class CharInFilter(django_filters.BaseInFilter, django_filters.CharFilter):
     pass

I spent some time myself running into this problem, and I think @carltongibson solution definitely helps some issues for me.

I was attempting to do something like:

class TestListFilter(Filter):
    field_class = forms.CharField

    def filter(self, qs, value):
        actual_filter = fields.Lookup(value, 'in')
        from pprint import pprint
        pprint(value)
        pprint(actual_filter)
        return qs

class BaseModelFilter(filters.FilterSet):
    id__in = TestListFilter(name='id', lookup_expr='in', widget=widgets.CSVWidget)

Using DRF & a url of: ?id__in=a,b,c

However it seems as though using widget=widgets.CSVWidget actually casts the list as a string somehow?

Printing the value of the filter results in "['a', 'b', 'c']"
the actual_filter has the quotes as well
Lookup(value="['a', 'b', 'c']", lookup_type='in')

Per the recommendation provided I switch things up to:

class UUIDInFilter(filters.BaseInFilter, filters.UUIDFilter):
    pass

class BaseModelFilter(filters.FilterSet):
    id = UUIDInFilter(name='id', lookup_expr='in')

And then I was able to use ?id=3e543ed4-9b90-403d-8f40-048297a9ac31,6bf953eb-3ac3-4ea1-8ce5-9f84dd392246

to get the expected results.

The "List as string" thing kind of seems like a bug or at least some doc changes maybe? I'm pretty unfamiliar with how the underlying functionality works though. Maybe it's just use error =)

CSVWidget is correctly returning a list of values, however CharField.clean() is coercing the list back into a text value, hence "['1', '2', '3']". It's not sufficient to pass CSVWidget to the filter - the form field needs to be overridden to accept a list of values.

The easiest way to get the correct field behavior is to mixin the BaseCSVFilter, as it properly constructs a form field that accepts a list of values.

Was this page helpful?
0 / 5 - 0 ratings