104 votes

Comment utiliser un dictionnaire pour mettre à jour des champs dans les modèles Django?

Supposons que j'ai un modèle comme celui-ci :

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

Puis-je créer un dictionnaire, puis insérer ou mettre à jour le modèle en l'utilisant ?

d = {"num_pages":40, author:"Jack", date:"3324"}

2 votes

Oui. Essayez. Recherchez l'opérateur ** dans le manuel de référence du langage Python. docs.python.org/reference/expressions.html#calls

0 votes

132voto

Thierry Lam Points 7888

Voici un exemple de création en utilisant votre dictionnaire d :

Book.objects.create(**d)

Pour mettre à jour un modèle existant, vous devrez utiliser la méthode filter du QuerySet. En supposant que vous connaissez la valeur pk du Book que vous souhaitez mettre à jour :

Book.objects.filter(pk=pk).update(**d)

35 votes

Je pense que la mise à jour fonctionne uniquement sur un QuerySet et non sur un seul objet.

21 votes

Faites attention : update() ne respecte pas les signaux. Voir la réponse de @leech ci-dessous.

0 votes

C'est brillant.

102voto

Utilisez ** pour créer un nouveau modèle. Parcourez le dictionnaire et utilisez setattr() pour mettre à jour un modèle existant.

De Django Rest Framework de Tom Christie

https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py

for attr, value in validated_data.items():
    setattr(instance, attr, value)
instance.save()

1 votes

Huh ? Pouvez-vous donner un exemple ? Donc, je devrais écrire une fonction personnalisée qui boucle à travers le dictionnaire ?

1 votes

@TIMEX: Veuillez lire. docs.python.org/reference/expressions.html#calls est très clair sur le fonctionnement de ceci.

1 votes

Pourriez-vous expliquer pourquoi l'utilisation de ** pour la mise à jour pourrait ne pas être une bonne idée?

77voto

leech Points 2672

Si vous savez que vous voulez le créer :

Book.objects.create(**d)

Si vous devez vérifier si une instance existe déjà, vous pouvez la trouver avec get_or_create:

instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
    for attr, value in d.items(): 
        setattr(instance, attr, value)
    instance.save()

Comme mentionné dans une autre réponse, vous pouvez également utiliser la fonction update sur le gestionnaire de requêtes, mais je crois que cela n'enverra pas de signaux (ce qui peut ne pas vous importuner si vous ne les utilisez pas). Cependant, vous ne devriez probablement pas l'utiliser pour modifier un seul objet :

Book.objects.filter(id=id).update()

0 votes

Ne votre code de création ne conduit-il pas à 2 requêtes à la base de données ? Une pour la création, l'autre pour .save() ?

2 votes

Oui, mais pas pour enregistrer. S'il a été créé, il y en aura un pour rechercher le livre (SELECT), puis un autre pour le mettre à jour (une déclaration UPDATE et non INSERT sera générée). Si le livre n'existe pas, il y en a un pour le chercher (SELECT) et le créer (INSERT).

13 votes

qui ne transmettra aucun signal : ne peut pas assez souligner cela.

12voto

Odiljon Djamalov Points 237

Si vous avez déjà un objet Django et que vous souhaitez mettre à jour son champ, vous pouvez le faire sans filtrer. car vous l'avez déjà, dans ce cas, vous pouvez :

votre_obj.__dict__.update(votre_dict)
votre_obj.save()

2voto

mka Points 78

Pour mettre à jour un enregistrement, vous pouvez utiliser une fonction très pratique:

class Book(models.Model):
    num_pages = ...
    author = ...
    date = ...

    def update(self,*args, **kwargs):
            for name,values in kwargs.items():
                try:
                    setattr(self,name,values)
                except KeyError:
                    pass
            self.save()

et ensuite:

d = {"num_pages":40, author:"Jack", date:"3324"}
book = Book.objects.first()
book.update(**d)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X