web-dev-qa-db-fra.com

Comment utiliser un dictionnaire pour mettre à jour les 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"}
52
TIMEX

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

Book.objects.create(**d)

Pour mettre à jour un modèle existant, vous devez utiliser la méthode QuerySet filter. En supposant que vous connaissiez la pk du livre que vous souhaitez mettre à jour:

Book.objects.filter(pk=pk).update(**d)
81
Thierry Lam

Si vous savez que vous voulez le créer:

Book.objects.create(**d)

En supposant que vous ayez besoin de rechercher une instance existante, vous pouvez la trouver avec get ou create:

instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
    for attr, value in d.iteritems(): 
        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 pense que cela n'enverra aucun signal (ce qui peut ne pas vous intéresser 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()
47
leech

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

Cadre de repos Django 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()
33

En plus d’autres réponses, voici une version un peu plus sécurisée pour éviter les problèmes avec les champs connexes:

def is_simple_editable_field(field):
    return (
            field.editable
            and not field.primary_key
            and not isinstance(field, (ForeignObjectRel, RelatedField))
    )

def update_from_dict(instance, attrs, commit):
    allowed_field_names = {
        f.name for f in instance._meta.get_fields()
        if is_simple_editable_field(f)
    }

    for attr, val in attrs.items():
        if attr in allowed_field_names:
            setattr(instance, attr, val)

    if commit:
        instance.save()

Il vérifie que le champ que vous essayez de mettre à jour est modifiable, qu'il ne s'agit pas d'une clé primaire ni d'un champ associé.

Exemple d'utilisation:

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

Les méthodes .create et .update pour les sérialiseurs DRF de luxe disposent d'un ensemble de champs limité et validé, ce qui n'est pas le cas pour la mise à jour manuelle.

0
Alexey Milogradov