Maison > développement back-end > Tutoriel Python > 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 ?

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 ?

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Libérer: 2024-02-06 09:48:12
avant
1097 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!

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