[Answered ]-How to use django-filter package for foreign key fields in Django?

1👍

The most general way to define a complicated filter is to use the method argument. I can’t say I completely understand your problem, but you can apply any filter for which you can dream up a queryset in this way. In outline:

import django-filters as DF

class SomeFilters( DF.FilterSet):

    name = DF.xxxFilter( method='my_method', field_name='object_field', label='whatever',  ...)
    ...

    def my_method( self, qs, name, value):
        # in here you create a new more restrictive queryset based on qs
        # to implement your filter, and return it.
        # name is the field name. Note, you don't have to use or follow it
        # value is the value that the user typed

        qs = qs.filter( ...) # or .exclude, or complicated stuff  
        return qs

Here’s a fairly simple method that I wrote to create an annotation with the value of a field stripped of spaces, and then to do a text-contains filter on that.

    def filter_array_desc( self, qs, name, value):
        value = value.replace(' ','')
        qs = qs.annotate(
            arr_d_nospaces = Replace( 'array_desc', Value(' '), Value('')) # delete all spaces
        ).filter(
            arr_d_nospaces__icontains = value )
        return qs

Here’s a general one that can be applied to any field through a ChoiceFilter to filter whether the field is blank or not:

    YESNO = (('Y','Yes'), ('N','No'))
    marr_b = FD.ChoiceFilter( field_name='marr', label='M_array is blank',  method='filter_blank_yesno', 
                              choices=YESNO, empty_label="Don't Care" )
    ...

    def filter_blank_yesno( self, qs, name, value):
        if value=="Y":
            return qs.filter(**{ name:'' })
        elif value=="N":
            return qs.exclude( **{ name:'' })
        raise ValueError(f'filter_blank_yesno received value="{value}" which is neither "Y" nor "N"')

Hope this helps. You will basically be filtering by following relationships between your models, using double-underscores to move between models, and possibly annotating and filtering on the anotation, or doing things with Q objects and suchlike.

Leave a comment