Tuesday, December 7, 2021

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

Use the inbuilt json library in python. Use json.dumps and json.loads
to convert the dictionary to json and vice versa.
On Thursday, 5 August 2021 at 04:17:38 UTC+5:30 shahee...@gmail.com wrote:
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)

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/3f2eb04c-3a7f-4bf8-bdf7-7fa787b2fe18n%40googlegroups.com.

No comments:

Post a Comment