Specify in which order to apply filters in django_filters.FilterSet
Within a django_filters.FilterSet
:
class SomeFilter(django_filters.FilterSet):
model = SomeModel
fields = {
"is_archived": ("exact",),
}
include_ancestors = django_filters.BooleanFilter(method="include_ancestors_filter")
def include_ancestors_filter(self, queryset, name, value):
pass
how can I specify that the filter field include_ancestors
should be applied after all other filter fields (e.g. is_archived
)?
This is needed in my case because including the ancestors depends on the result set (i.e. depends on what children have been included based on all other filters).
You can probably "hack" this into it by moving the include_ancestors
down the list of values:
class MoveDownForm:
move_down_field = 'include_ancestors'
@property
def cleaned_data(self):
new = old = super().cleaned_data
if self.move_down_field in old:
new = {k: v for k, v in old.items() if k != self.move_down_field}
new['move_down_field'] = old['move_down_field']
return new
and then work with:
class SomeFilter(django_filters.FilterSet):
class Meta:
model = SomeModel
form = MoveDownForm
fields = {
"is_archived": ("exact",),
}
include_ancestors = django_filters.BooleanFilter(method="include_ancestors_filter")
def include_ancestors_filter(self, queryset, name, value):
pass
But I would test this with two custom filters and check the order of printing if you swap the querystring parameters.
class SomeFilter(django_filters.FilterSet):
include_ancestors = django_filters.BooleanFilter(required=False) # dont add a method
class Meta:
model = SomeModel
fields = {"is_archived": ["exact"]}
@property
def qs(self):
queryset = super().qs # it wont be filtered here
if self.form.cleaned_data.get("include_ancestors"):
queryset = self._apply_ancestor_logic(queryset)
return queryset
def _apply_ancestor_logic(self, queryset):
pass
I would do something like this, where I wouldn't assign a method
name to the filter
so that Django
leaves the ancestor filter
when doing the queryset
call.
Once all the filters
are used, i will check if the ancestor
logic needs to be added to the returned queryset
or not.