Django filter JSONField list of dicts

I run Django 1.9 with the new JSONField and have the following Test model :

class Test(TimeStampedModel):
    actions = JSONField()

Let's say the action JSONField looks like this :

[
  {
    "fixed_key_1": "foo1",
    "fixed_key_2": {
      "random_key_1": "bar1",
      "random_key_2": "bar2",
    }
  },
  {
    "fixed_key_1": "foo2",
    "fixed_key_2": {
      "random_key_3": "bar2",
      "random_key_4": "bar3",
    }
  }
]

I want to be able to filter the foo1 and foo2 keys for every item of the list. When I do :

>>> Test.objects.filter(actions__1__fixed_key_1="foo2")

The Test is in the queryset. But when I do :

>>> Test.objects.filter(actions__0__fixed_key_1="foo2")

It isn't, which makes sense. I want to do something like :

>>> Test.objects.filter(actions__values__fixed_key_1="foo2")

Or

>>> Test.objects.filter(actions__values__fixed_key_2__values__contains="bar3")

And have the Test in the queryset.

Any idea if this can be done and how ?


If you wan't to filter your data by one of fields in your array of dicts, you can try this query:

Test.objects.filter(actions__contains=[{'fixed_key_1': 'foo2'}])

It will list all Test objects that have at least one object in actions field that contains key fixed_key_1 of value foo2 .

Also it should work for nested lookup, even if you don't know actual indexes:

Test(actions=[
    {'fixed_key_1': 'foo4', 'fixed_key_3': [
        {'key1': 'foo2'},
    ]}
}).save()

Test.objects.filter(actions__contains=[{'fixed_key_3': [{'key1': 'foo2'}]}])

In simple words, contains will ignore everything else.

Unfortunately, if nested element is an object, you must know key name. Lookup by value won't work in that case.


You should be able to use a __contains lookup for this, as documented here. The lookup would still be like what DhiaTN recommended above. So, something like this should work:

Test.objects.filter(actions__contains={'fixed_key_1': 'foo2'})

You can use the django-jsonfield package, I guess it's already the one you are using.

from jsonfield import JSONField
class Test(TimeStampedModel):
    actions = JSONField()

So to search to make a search with a specific property, you can just do this:

def test_filter(**kwargs):
    result = Test.objects.filter(actions__contains=kwargs)
    return result

If you are using PostgreSQL, maybe you can take advantage of PostgreSQL specific model fields.

PS: If you are dealing with a lot of JSON structure you have maybe to consider using NoSQL Database.

链接地址: http://www.djcxy.com/p/38654.html

上一篇: 在Django上使用ManyToMany queryset的单个过滤器

下一篇: Django过滤器JSONField字典列表