pythondjangodjango-filter

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).


Solution

  • 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.