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.

Verwandte Themen