carltongibson / django-filter

A generic system for filtering Django QuerySets based on user selections
https://django-filter.readthedocs.io/en/main/
Other
4.41k stars 766 forks source link

Enhancement: A simple way to add pseudo-lookups for FilterSet's Meta.fields #1575

Open WhiteSage opened 1 year ago

WhiteSage commented 1 year ago

One of the proposed solutions in the documentation for filtering for empty strings is adding the lookup __isempty. This can be done by registering it at the Django level (and fiddling directly with the SQL compiler) or by adding a filter which responds to the specified lookup.

Automatic generation through FilterSet.Meta.fields however fails, even if we overwrite the FilterSet.filter_for_lookup() function:

    @classmethod
    def filter_for_lookup(cls, field, lookup_type):

        if lookup_type == "isempty":
            return EmptyStringFilter, {}

        return super().filter_for_lookup(field, lookup_type)

The reason is FilterSet.filter_for_field() calls the resolve_field() function on the utils module, which then uses the Django machinery to determine which part are transformers and which part is lookup, and what field type results after applying the transforms. There is no way to override the resolve_field() call without overriding the whole FilterSet.filter_for_field() function.

It would be nice if some support could be added for custom lookups. This seems a complex issue, but at least the resolve_field() call could get wrapped into a FilterSet class function which can be easily overriden in case we have to support custom lookups.