9

Ich betreibe Django 1.9 mit dem neuen JSONField und haben folgende Testmodell:Django filtern JSONField Liste der dicts

class Test(TimeStampedModel): 
    actions = JSONField() 

Lassen Sie uns sagen, dass die Aktion JSONField wie folgt aussieht:

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

Ich möchte in der Lage sein, die foo1 und foo2 Schlüssel für jedes Element der Liste zu filtern. Wenn ich tun:

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

Der Test in dem queryset ist. Aber wenn ich das tue:

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

Es ist nicht, was Sinn macht. Ich möchte wie etwas tun:

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

Oder

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

Und haben den Test in der queryset.

Irgendeine Idee, wenn dies getan werden kann und wie?

Antwort

2

Sie können das django-jsonfield Paket verwenden, ich denke es ist bereits das, das Sie verwenden.

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

So suchen eine Suche mit einer bestimmten Eigenschaft zu machen, können Sie dies nur tun:

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

Wenn Sie PostgreSQL verwenden, vielleicht können Sie die Vorteile von PostgreSQL specific model fields nehmen.

PS: Wenn Sie mit einer Menge JSON-Struktur arbeiten, müssen Sie vielleicht NoSQL-Datenbank in Betracht ziehen.

+1

Ich benutze tatsächlich bereits PostgreSQLs JSONField-spezifisches Modellfeld ('von django.contrib.postgres.fields JSONField importieren ').Deine Lösung funktioniert, wenn 'your_property' bekannt ist (' fixed_key_1' und 'fixed_key_2' in meinem Fall), aber wie kann ich tun, wenn ich' your_property' nicht weiß ('random_key_ #' in meinem Fall)? – Scentle5S

+0

Sie sollten '{'fixed_key_1': 'foo2'}' Ihren Parameter, ich habe den Code mit generischen Funktion aktualisiert. – DhiaTN

+1

Die Sache ist, ich weiß nicht besonders 'your_property'. Es könnte alles sein und ich interessiere mich nicht einmal dafür, ich möchte nur wissen, ob das JSONField eine beliebige Zeichenfolge in einem seiner Werte enthält, unabhängig von der Tiefe. – Scentle5S

2

Sie sollten in der Lage sein, einen __contains Lookup dafür zu verwenden, wie dokumentiert here. Das Nachschlagen wäre immer noch wie das oben von DhiaTN empfohlene. So sollte in etwa so funktionieren:

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

Wenn Sie Ihre Daten filtern wan't von einem der Felder in der Reihe von dicts, können Sie diese Abfrage versuchen:

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

Es listet Alle Test Objekte, die mindestens ein Objekt im Feld actions enthalten, das den Schlüssel fixed_key_1 mit dem Wert foo2 enthält.

Auch sollte es für verschachtelte Lookup arbeiten, auch wenn Sie nicht unbedingt Indizes wissen:

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

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

In einfachen Worten, enthält, wird alles andere ignorieren.

Wenn das verschachtelte Element ein Objekt ist, müssen Sie leider den Schlüsselnamen kennen. Suche nach Wert wird in diesem Fall nicht funktionieren.