many-to-manydjango-rest-frameworkdjango-filterdjango-taggit

django-filters BaseInFilter with CharFilter returns no results when empty with django-rest-framework


I'm using django-taggit for tags, so it's essentially just a m2m relationship.

The following lets me filter tags with a comma-separated string.

However, the browsable API with django-rest-framework submits empty filter parameters, and &tags= with no corresponding values is filtering out ALL results. Have I done something wrong below? Or is this an issue with the browsable API?

class TagsFilter(django_filters.filters.BaseInFilter, django_filters.filters.CharFilter):
    pass

class NuggetFilter(filters.FilterSet):
    tags = TagsFilter(name="tags__name", distinct=True)

Solution

  • This is a bug in django-filter (pull request). The CSV widget is parsing the blank value as a list containing one empty string, [''] instead of an empty list. The value isn't technically empty, so it passes the filter's empty check, resulting in the following query:

    Nugget.objects.filter(tags__name__in=[''])
    

    To get around this in the short term, you can override the filter method like so:

    class TagsFilter(django_filters.filters.BaseInFilter, django_filters.filters.CharFilter):
    
        def filter(self, qs, value):
            if value == ['']:
                return qs
            return super(TagsFilter, self).filter(qs, value)