Comment mettre à jour les valeurs de plusieurs clés dans un JsonField à l'aide de la méthode .update() à l'aide de l'ORM de Django ?

WBOY
Libérer: 2024-02-06 09:48:12
avant
977 Les gens l'ont consulté

如何使用 Django 的 ORM 使用 .update() 方法更新 JsonField 中多个键的值?

Contenu de la question

J'ai un champ de modèle que j'essaie d'utiliser avec celui de Django .update() 方法进行更新。该字段是一个 jsonfield。我通常会在这个领域保存一本字典。例如{"test": "是", "prod": "否"}

Voici le modèle :

class question(models.model):
    # {"test": "yes", "prod": "no"}
    extra_data = models.jsonfield(default=dict, null=true, blank=true)
Copier après la connexion

Je peux mettre à jour les clés dans le dictionnaire en utilisant cette requête (qui fonctionne très bien d'ailleurs) :

Question.filter(id="123").update(meta_data=Func(
                        F("extra_data"),
                        Value(["test"]),
                        Value("no", JSONField()),
                        function="jsonb_set",
                    ))
Copier après la connexion

Maintenant, la question est la suivante : existe-t-il un moyen de mettre à jour plusieurs clés (dans mon cas, deux) à la fois en utilisant .update() comme indiqué dans la requête ci-dessus ?

Je souhaite utiliser la méthode .update() 方法而不是 .save() au lieu de .save() pour y parvenir afin d'éviter d'appeler la fonction de signal post_save.


Bonne réponse


Avertissement : cela aura l'air moche.

Je l'ai fait dans le passé, bien qu'en utilisant du SQL pur, pas Django. L'idée est d'appeler de manière récursive jsonb_set(). Chaque appel définit une clé.

Donc, en SQL, pour définir une clé {"test":"yes","prod":"no"} vous faites :

update question set meta_data = jsonb_set(jsonb_set(extra_data, '{test}', '"yes"'::jsonb), '{prod}', '"no"'::jsonb)
where id = 123;
Copier après la connexion

Veuillez noter qu'il existe deux appels imbriqués à jsonb_set, celui le plus interne est utilisé meta_data et celui le plus externe reçoit le résultat le plus interne.

Donc l'équivalent de Django ressemble à ceci (note, non testé) :

question.filter(id="123").update(
    meta_data=func(
        func(
            f("extra_data"),
            value(["test"]),
            value("yes", jsonfield()),
            function="jsonb_set",
        ),
        value(["prod"]),
        value("no", jsonfield()),
        function="jsonb_set",
    ))
Copier après la connexion

Ou vous pouvez créer une fonction récursive qui renvoie le désordre pour vous, en définissant un élément à la fois :

def recursive_jsonb_set(original, **kwargs):
    if kwargs:
        key, value = kwargs.popitem()
        return Func(
            recursive_jsonb_set(original, **kwargs),
            Value(key.split('__')),
            Value(value, JSONField()),
            function="jsonb_set")
    else:
        return original

Question.filter(id="123").update(
    meta_data=recursive_jsonb_set(F("extra_data"), test="yes", prod="no", other__status="done"))
Copier après la connexion

Veuillez noter la fonction '__' pour mettre à jour les enfants.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!