How to update part of a JSONField with a computed value?

561 views
Skip to first unread message

Shaheed Haque

unread,
Aug 4, 2021, 6:47:38 PM8/4/21
to django...@googlegroups.com
Hi,

I'm using Django 3.2 on Postgres12, and I have a model with a JSONField which contains a simple dict (actually, a Django formset :-)). I would like to update just one value in the dict. I can get this to work when the new value is a hardcoded numeric 333 (quoted, as seems to be needed) like this:
    pay_items.update(inputs=JSONBSet('inputs', ['inputs-0-value'], Value("333"), True))
where JSONBSet is a Func, as indicated below. However, I'd like to actually compute the value. I've tried a variety of things, without success. Here is one attempt:

    pay_items.update(inputs=JSONBSet('inputs', ['inputs-0-value'],
Cast(F('inputs__inputs-0-value'), FloatField()) + Value("3"),
True))

This fails like this:

ERROR:  function jsonb_set(jsonb, unknown, double precision, boolean) does not exist at character 42
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
STATEMENT:  UPDATE "paiyroll_payitem" SET "inputs" = JSONB_SET("paiyroll_payitem"."inputs", '{inputs-0-value}', (CAST(("paiyroll_payitem"."inputs" -> 'inputs-0-value') AS double precision) + '3'), true) WHERE "paiyroll_payitem"."id" IN (...))


I've tried all sorts of variants with Cast, ExpressionWrapper and so on to no avail, so I'd be grateful for any shove in the right direction!

Thanks, Shaheed

Encls: implementation of JSONBSet derived from https://code.djangoproject.com/ticket/32519 and related threads:
class JSONBSet(Func):
function = 'JSONB_SET'
arity = 4
output_field = CharField()

def __init__(self, field, path, value, create: bool = True):
path = Value('{{{0}}}'.format(','.join(path)))
create = Value(create)
super().__init__(field, path, value, create)

Bazil M H

unread,
Dec 7, 2021, 8:58:19 AM12/7/21
to Django users
Use the inbuilt json library in python. Use json.dumps and json.loads
to convert the dictionary to json and vice versa.
Reply all
Reply to author
Forward
0 new messages