9

biegnę Django 1.9 z nowym JSONField i mieć następujący model testowy:Django filtrować JSONField listę dicts

class Test(TimeStampedModel): 
    actions = JSONField() 

Powiedzmy akcja JSONField wygląda następująco:

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

chcę móc filtrować klucze foo1 i foo2 dla każdego elementu listy. Kiedy zrobić:

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

test jest w queryset. Ale kiedy to zrobię:

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

To nie jest, co ma sens. Chcę zrobić coś takiego:

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

Albo

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

I mieć testu w queryset.

Każdy pomysł, czy można to zrobić i jak?

Odpowiedz

2

Możesz użyć pakietu django-jsonfield, chyba to już ten, którego używasz.

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

więc szukać, aby dokonać wyszukiwania z konkretnej nieruchomości, można po prostu to zrobić:

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

Jeśli używasz PostgreSQL, może skorzystać z PostgreSQL specific model fields.

PS: Jeśli masz do czynienia z dużą strukturą JSON, możesz rozważyć użycie bazy danych NoSQL.

+1

Właściwie używam już pola modelu specyficznego dla PostgreSQL-a JSONField ('from django.contrib.postgres.fields import JSONField').Twoje rozwiązanie działa, gdy znana jest 'twoja_właściwość' (' fixed_key_1' i 'fixed_key_2' w moim przypadku), ale jak mam zrobić, gdy nie znam' twojej_właściwości' ("random_key_ #" w moim przypadku)? – Scentle5S

+0

Powinieneś zrobić '{'fixed_key_1': 'foo2'}' 'twój parametr, zaktualizowałem kod za pomocą ogólnej funkcji. – DhiaTN

+1

Chodzi o to, że nie znam szczególnie 'twojej_property'. Może to być cokolwiek i nawet o to nie dbam, chcę tylko wiedzieć, czy JSONField zawiera dany łańcuch w dowolnej jego wartości, bez względu na głębokość. – Scentle5S

2

Powinieneś być w stanie użyć do tego sprawdzenia __contains, zgodnie z dokumentacją here. Wyszukiwanie nadal będzie podobne do zalecanego przez DhiaTN. Tak, coś jak to powinno działać:

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

Jeśli wa do filtrowania danych przez jednego z pól w tablicy dicts, można spróbować to zapytanie:

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

To będzie lista wszystkie obiekty z co najmniej jednym obiektem w polu Test zawierającym klucz fixed_key_1 o wartości foo2.

również powinno działać dla zagnieżdżonego odnośnika, nawet jeśli nie wiem rzeczywistych indeksów:

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

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

W prostych słowach, zawiera zignoruje wszystko.

Niestety, jeśli elementem zagnieżdżonym jest obiekt, należy znać nazwę klucza. Wyszukiwanie według wartości nie będzie działać w takim przypadku.