Django filtro JSONField lista de dictados

Ejecuto Django 1.9 con el nuevo JSONField y tengo el siguiente modelo de prueba:

class Test(TimeStampedModel): actions = JSONField() 

Digamos que la acción JSONField se ve así:

 [ { "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", } } ] 

Quiero poder filtrar las teclas foo1 y foo2 para cada elemento de la lista. Cuando lo hago :

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

La prueba está en el queryset. Pero cuando lo hago :

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

No lo es, lo que tiene sentido. Quiero hacer algo como:

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

O

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

Y tener la prueba en el queryset.

¿Alguna idea de si esto se puede hacer y cómo?

Si no quiere filtrar sus datos por uno de los campos de su conjunto de dicts, puede intentar esta consulta:

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

fixed_key_1 todos Test objetos de Test que tienen al menos un objeto en el campo de actions que contiene la clave fixed_key_1 de valor foo2 .

También debería funcionar para búsquedas anidadas, incluso si no conoce los índices reales:

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

En palabras simples, contiene ignorará todo lo demás.

Desafortunadamente, si el elemento nested es un objeto, debe conocer el nombre de la clave. La búsqueda por valor no funcionará en ese caso.

Puedes usar el paquete django-jsonfield , supongo que ya es el que estás usando.

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

Entonces, para realizar una búsqueda con una propiedad específica, puede hacer esto:

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

Si está utilizando PostgreSQL, tal vez pueda aprovechar los campos de modelos específicos de PostgreSQL.

PD: Si está lidiando con una gran cantidad de estructura JSON, quizás deba considerar el uso de la base de datos NoSQL.

Debería poder usar una búsqueda __contains esto y pasar los valores consultados como se indica en la lista tal como se documenta aquí . La búsqueda se comportaría exactamente como ArrayField. Entonces, algo como esto debería funcionar:

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