django-url-filter
django-url-filter copied to clipboard
Fallback behavior for the callable filter
Hi I have a callable filter that handles a custom lookup that I implemented:
class StatusFilter(CallableFilter):
@form_field_for_filter(forms.CharField())
def filter_has_any_keys_for_django(self, queryset, spec):
value = spec.value.split(',')
if spec.is_negated:
return queryset.exclude(status__has_any_keys=value)
else:
return queryset.filter(status__has_any_keys=value)
@form_field_for_filter(forms.CharField())
def filter_contains_for_django(self, queryset, spec):
if spec.is_negated:
return queryset.exclude(status__contains=spec.value)
else:
return queryset.filter(status__contains=spec.value)
And it works great. The issue is that if the callable filter doesn't support other types of lookups, I want it to fall back to the default way of handling the filters, so for example if I try to specify a query parameter like ".../?status=["complete","succeeded"] then I get an error:
AssertionError: StatusFilter was not provided form_field parameter in initialization (e.g. StatusFilter(form_field=CharField)) and form_field was not provided for the lookup. If the lookup is a custom filter callable you should provide form_field by using @form_field_for_filter decorator. If the lookup is a normal lookup, then please either provide form_field parameter or overwrite get_form_field().
Is there a mechanism for this?
Thanks -Selim
not any simple way at the moment
That's ok, it was as simple as adding the following:
@form_field_for_filter(forms.CharField())
def filter_exact_for_django(self, queryset, spec):
value = json.loads(spec.value)
f = queryset.filter if not spec.is_negated else queryset.exclude
return f(status=value)
In order to solve this problem, I wrote FallbackCallableFilter:
class FallbackCallableFilter(CallableFilter):
def get_spec(self, config):
spec = super(CallableFilter, self).get_spec(config)
try:
spec.filter_callable = self._get_filter_method_for_lookup(spec.lookup)
except AttributeError:
pass
return spec
Perhaps this could be part of the project?
Note that @selimt's solution is not complete, as there are many other lookups besides __exact (__icontains, __in etc.).