Versionen: Django 1.10 und Postgres 9.6Django/PostgresQL jsonb (JSONField) - konvertieren auswählen und aktualisieren in einer Abfrage
Ich versuche, ohne eine Rundreise zu Python eine verschachtelte JSONField der Schlüssel in Position zu ändern. Grund ist es, Race Conditions und Mehrfachabfragen zu vermeiden, die das gleiche Feld mit unterschiedlichen Updates überschreiben.
Ich versuchte Kette, die Methoden in der Hoffnung, dass Django eine einzelne Abfrage machen würde, aber es als Zweierkomplement wird protokolliert:
Original-Feldwert (Demo nur reale Daten sind komplexer):
from exampleapp.models import AdhocTask
record = AdhocTask.objects.get(id=1)
print(record.log)
> {'demo_key': 'original'}
Abfrage:
from django.db.models import F
from django.db.models.expressions import RawSQL
(AdhocTask.objects.filter(id=25)
.annotate(temp=RawSQL(
# `jsonb_set` gets current json value of `log` field,
# take a the nominated key ("demo key" in this example)
# and replaces the value with the json provided ("new value")
# Raw sql is wrapped in triple quotes to avoid escaping each quote
"""jsonb_set(log, '{"demo_key"}','"new value"', false)""",[]))
# Finally, get the temp field and overwrite the original JSONField
.update(log=F('temp’))
)
Que Geschichte ry (zeigt dies als zwei getrennte Abfragen):
from django.db import connection
print(connection.queries)
> {'sql': 'SELECT "exampleapp_adhoctask"."id", "exampleapp_adhoctask"."description", "exampleapp_adhoctask"."log" FROM "exampleapp_adhoctask" WHERE "exampleapp_adhoctask"."id" = 1', 'time': '0.001'},
> {'sql': 'UPDATE "exampleapp_adhoctask" SET "log" = (jsonb_set(log, \'{"demo_key"}\',\'"new value"\', false)) WHERE "exampleapp_adhoctask"."id" = 1', 'time': '0.001'}]
Das ist ein schönes Stück Code ist dank Michael. Ich hatte noch keine Erfahrung, 'Func' vorher zu erben, also ist das ein großartiger Zeiger. Auch gut zu sehen Typ Hinting in der Praxis; es hilft definitiv Lesbarkeit und die Absicht für den Code zu verstehen. –