我在 PostgreSQL 上有一个 Django JSONField,其中包含一个字典,我想使用queryset.update()
使用数字(最终是计算得出的)值批量更新一个(最终是几个)键。我看到有关于添加的讨论对此有更好的支持 https://code.djangoproject.com/ticket/32519 and an 旧扩展 https://github.com/primal100/django_postgres_extensions#jsonfield,但目前看来我需要一种 DIY 方法。根据这些参考资料,我得出了以下结论:
from django.db.models import Func, Value, CharField, FloatField, F, IntegerField
class JSONBSet(Func):
"""
Update the value of a JSONField for a specific key.
"""
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)
对于像这样的非计算“数字字符串”值来说,这似乎工作得很好:
# This example sets the 'nestedkey' to numeric 199.
queryset.update(inputs=JSONBSet('inputs', ['nestedkey'], Value("199"), False))
对于仔细引用的字符串:
# This example sets the 'nestedkey' to 'some string'.
queryset.update(inputs=JSONBSet('inputs', ['nestedkey'], Value('"some string"'), False))
但它不适用于数字:
queryset.update(inputs=JSONBSet('inputs', ['nestedkey'], Value(1), False))
{ProgrammingError}function jsonb_set(jsonb, unknown, integer, boolean) does not exist
LINE 1: UPDATE "paiyroll_payitem" SET "inputs" = JSONB_SET("paiyroll...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
根据提示,我尝试了显式强制转换Value(1, IntegerField())
。我不确定我哪里出错了。