abelcastro.dev

Django ORM - call queryset update() in json field when the key to update is not present

2022-05-31

PostgresDjango

I learnt today that this is not possible with the Django ORM to call update in a queryset json field when the key that you want to update is not present. For example:

queryset.update(json_data__key="something")

This will return FieldDoesNotExist: ModelClass has no field named 'json_data__key' because some objects does not have the key “key”.

I found in this stackoverflow post a great solution for this.

from django.db.models.expressions import Func

class JsonSetValue(Func):
    function = "jsonb_set"
    template = "%(function)s(%(expressions)s, '{\"%(keyname)s\"}','\"%(new_value)s\"', %(create_missing)s)"
    arity = 1

    def __init__(
        self,
        expression: str,
        keyname: str,
        new_value: str,
        create_missing: bool = False,
        **extra,
    ):
        super().__init__(
            expression,
            keyname=keyname,
            new_value=new_value,
            create_missing="true" if create_missing else "false",
            **extra,
        )

With help of JsonSetValue you will be able to do the following:

queryset.update(
    json_data=JsonSetValue(
        "json_data",
        keyname="key",
        new_value="something",
        create_missing=True,
    )
)