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.