Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Altering django-filter default behaviour

This is a django-filter app specific guestion.

Has anyone tried to introduce conditions for the filters to query according to the condition?

Let me give an example:

Suppose we have a Product model. It can be filtered according to its name and price.

The default django-filter behaviour is that, as we use more filters and chain them together, they filter data using AND statements (it narrows the search).

I'd like to change this behaviour and add a ChoiceFilter, say with two options: AND as well as OR. From this point, the filter should work according to what a user have selected.

Eg. if a user query for products with name__startswith="Juice" OR price__lte=10.00, it should list all the products with names starting with Juice as well as products with price below 10.00.

Django-filter docs say that the filter can take an argument:

action

An optional callable that tells the filter how to handle the queryset. It recieves a 
QuerySet and the value to filter on and should return a Queryset that is filtered 
appropriately.

which seems to be what I am looking for, but the docs lacks any further explanation. Suggestions please?

@EDIT:

This is views.py:

def product_list(request):
    f = ProductFilter(request.GET, queryset=Product.objects.all())
    return render_to_response('my_app/template.html', {'filter': f})
like image 729
nutship Avatar asked May 26 '26 15:05

nutship


1 Answers

Because of the way the final queryset is constructed, making each filter be ORed together is difficult. Essentially, the code works like this:

FilterSet, filterset.py line 253:

@property
def qs(self):
    qs = self.queryset.all()
    for filter_ in self.filters():
        qs = filter_.filter(qs)

Filters, filters.py line 253:

def filter(self, qs):
    return qs.filter(name=self.value)

Each filter can decide how to apply itself to the incoming queryset, and all filters, as currently implemented, filter the incoming queryset using AND. You could make a new set of filters that OR themselves to the incoming queryset, but there is no way of overriding the behaviour from the FilterSet side.

like image 92
Tim Heap Avatar answered May 28 '26 04:05

Tim Heap



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!