Search code examples
djangodjango-filterquery-string

How to build filter class using django-filter that allows to query by multiple values of one model field


I have to build endpoint that must allow to filter by multiple values. It must looks like this:

http://example.com/page?field=1&field=2&filed=3

Lets say that field is an IntegField of MyModel. An I want to query by any value in this field.

I want to execute such or similiar query + validate the list of query params

MyModel.objects.filter(field__in=[1,2,3])

django-filter(https://django-filter.readthedocs.io/en/stable/) library looks promising but in the documentation I have not found an easy way to do something so simple. How can I achieve this?

Validation is also imortant. I dont want to allow to execute query with such param field=yolo

So far I have ended up with code that does not support validation

import django_filters as df
from django.forms.widgets import SelectMultiple
    

class MyFilter(df.FilterSet):
    id = df.Filter(required=False, field_name="id", widget=SelectMultiple(), lookup_expr="in")

    class Meta:
        model = MyModel
        fields = ["id"]

Solution

  • Maybe not the most elegant way, but this is how I achieved the goal:

    from django_filters.fields import BaseCSVField
    from django_filters.widgets import QueryArrayWidget
    
    class MyBaseCSVField(BaseCSVField):
        base_widget_class = QueryArrayWidget
    
    
    class MyBaseInFilter(df.BaseInFilter):
        base_field_class = MyBaseCSVField
    
    
    class NumberInFilter(MyBaseInFilter, df.NumberFilter):
        pass
    
    
    class MytFilter(df.FilterSet):
        field = NumberInFilter()
    
        class Meta:
            modem = MyModel
            fields = ("field", )
    

    So the key here is the QueryArrayWidget and from the docstrin:

     1. Values can be provided as csv string:  ?foo=bar,baz
     2. Values can be provided as query array: ?foo[]=bar&foo[]=baz
     3. Values can be provided as query array: ?foo=bar&foo=baz
    

    Generally this library is not well documented in my honest opinion.