Django-filter: JSONField with ModelMultipleChoiceFilter

Created on 11 Jul 2019  ·  2Comments  ·  Source: carltongibson/django-filter

Hello.
I read a lot Issue, but i don't understand why my filter does not work?
I have model:

class Product(models.Model):
    name = models.CharField(max_length=120)
    properties = JSONField(default=dict, blank=True, null=True)

and Filter

class ProductFilter(FilterSet):
    color = filters.ModelMultipleChoiceFilter(
        queryset=Product.objects.values_list('properties__color', flat=True).distinct(),
        field_name='properties',
        to_field_name='properties__color__contains',
        conjoined=True,
        )

    class Meta:
        model = Product
        fields = {
            'color': 'color__contains',
        }

My item

{
    "id": 10,
    "name": "Test_3",
    "properties": {
        "color": "Black",
        "invertor technology": false,
        "service area, m²": 24
    },
},

But i have this SQL query

SELECT ••• FROM "products_product" WHERE ("products_product"."properties" #> ARRAY['color','contains']) IN ('"Black"')

If i change this:

to_field_name='properties__color'

I have:

SELECT ••• FROM "products_product" WHERE ("products_product"."properties" -> 'color') IN ('"Black"')

And i have Error: 'str' object has no attribute 'properties__color'
How i can have:

SELECT ••• FROM "products_product" WHERE ("products_product"."properties" -> 'color') @> '"Black"'

Or may be you tell me what SQL query more correct?
If i use this CharFilter:

color2 = filters.CharFilter(
        field_name='properties',
        lookup_expr='color__contains',
    )

All work wonderful, but I need have choose more one values this filter.

Most helpful comment

There are a few things wrong here

  • ModelMultipleChoiceFilter is intended to work across foreign keys.
    For example, find Articles with the given Tags.
  • to_field_name is meant to correspond with ForeignKey.to_field.
  • field_name should only contains the model field. lookup_expr should contain the lookup expressions (like contains).

It looks like you probably want to use AllValuesMultipleFilter, although I'm not entirely certain if it will work with JSONFields. Try:

class ProductFilter(FilterSet):
    color = filters.AllValuesMultipleFilter(
        field_name='properties__color',
        lookup_expr='contains,
    )

All 2 comments

There are a few things wrong here

  • ModelMultipleChoiceFilter is intended to work across foreign keys.
    For example, find Articles with the given Tags.
  • to_field_name is meant to correspond with ForeignKey.to_field.
  • field_name should only contains the model field. lookup_expr should contain the lookup expressions (like contains).

It looks like you probably want to use AllValuesMultipleFilter, although I'm not entirely certain if it will work with JSONFields. Try:

class ProductFilter(FilterSet):
    color = filters.AllValuesMultipleFilter(
        field_name='properties__color',
        lookup_expr='contains,
    )

Oh it's work amazing, I spend this problem three day trying to sort out this problem.
Thank you so much!

Was this page helpful?
0 / 5 - 0 ratings