sélectionner et mettre à jour l'enregistrement de la base de données avec un seul jeu de requêtes


140

Comment exécuter une instruction updateand selectsur le même querysetplutôt que de devoir faire deux requêtes: - une pour sélectionner l'objet - et une pour mettre à jour l'objet

L'équivalent en SQL serait quelque chose comme:

update my_table set field_1 = 'some value' where pk_field = some_value

Réponses:


269

Utilisez la méthode d' objetupdate queryset :

MyModel.objects.filter(pk=some_value).update(field1='some value')

95
Juste un avertissement ... si vous utilisez la updateméthode comme celle-ci, aucun signal attaché à ce modèle ou autre "code" ne fonctionnera contre les objets. Juste un pointeur de quelqu'un qui a été brûlé :)
— DMac the Destroyer

@DMactheDestroyer mec merci pour cette information précieuse. Devrions-nous alors utiliser l'ancienne méthode de mise à jour? (ie) obtenir et enregistrer?

@learning well mec, tout dépend de votre scénario. La updateméthode est idéale pour les mises à jour de masse, mais elle devrait déclencher un avertissement dans votre tête lorsque vous l'utilisez que vous devez examiner tous les signaux attachés à cet objet qui pourraient également avoir besoin d'être déclenchés manuellement
— DMac the Destroyer

3
Est-il possible d'accéder à l'instance de modèle actuelle dans la fonction de mise à jour? commeMyModel.objects.filter(pk=some_value).update(field1=self.data)
— Dipak

8
@DipakChandranP Vous devriez poser une nouvelle question plutôt que de mettre des commentaires sur une de six ans. Mais les expressions F () sont probablement ce que vous voulez.
— Daniel Roseman le

70

Les objets de base de données Django utilisent la même méthode save () pour créer et modifier des objets.

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

Comment Django sait UPDATE ou INSERT
Si l'attribut de clé primaire de l'objet est défini sur une valeur qui prend la valeur True (c'est-à-dire une valeur autre que None ou la chaîne vide), Django exécute un UPDATE. Si l'attribut de clé primaire de l'objet n'est pas défini ou si UPDATE n'a rien mis à jour, Django exécute un INSERT.

Réf .: https://docs.djangoproject.com/fr/1.9/ref/models/instances/


17

Cette réponse compare les deux approches ci-dessus. Si vous souhaitez mettre à jour de nombreux objets sur une seule ligne, optez pour:

# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')

Sinon, vous devrez parcourir l'ensemble de requêtes et mettre à jour des objets individuels:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. L'approche 1 est plus rapide car elle n'effectue qu'une seule requête de base de données, par rapport à l'approche 2 qui effectue des requêtes de base de données «n + 1». (Pour n éléments de l'ensemble de requêtes)

  2. La première approche fait une requête db, c'est-à-dire UPDATE, la seconde en fait deux: SELECT puis UPDATE.

  3. Le compromis est que, supposons que vous ayez des déclencheurs, comme la mise à jour updated_onou tout autre champ connexe, il ne sera pas déclenché lors de la mise à jour directe, c'est-à-dire de l'approche 1.

  4. L'approche 1 est utilisée sur un jeu de requêtes, il est donc possible de mettre à jour plusieurs objets à la fois, pas dans le cas de l'approche 2.


Concernant 1. - Je pense que le résultat de la requête est mis en cache lors du premier appel à la requête, il n'y a donc en fait qu'un seul appel à DB.
— user2340939

2

seulement dans un cas dans les serializerchoses, vous pouvez mettre à jour de manière très simple!

my_model_serializer = MyModelSerializer(
    instance=my_model, data=validated_data)
if my_model_serializer.is_valid():

    my_model_serializer.save()

seulement dans un cas dans les formchoses!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()

Je pense que les sérialiseurs proviennent de Djanog Rest Framework et non de Django proprement dit.
— Code-Apprentice

1
Ouais, cependant, Django formvient de Django Proper.
— Jamil Noyda le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.