selezionare e aggiornare il record del database con un singolo set di query


140

Come faccio a eseguire una updatee selectistruzioni sullo stesso querysetanziché dover fare due query: - una per selezionare l'oggetto - e una per aggiornare l'oggetto

L'equivalente in SQL sarebbe qualcosa di simile:

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

Risposte:


269

Utilizzare il metodo dell'oggettoupdate queryset :

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

95
Solo un discreto avvertimento ... se usi il updatemetodo in questo modo, tutti i segnali collegati a quel modello o altre "cose ​​del codice" non funzioneranno contro gli oggetti. Solo un puntatore di qualcuno che è stato bruciato :)
DMac the Destroyer

@DMactheDestroyer amico grazie per le preziose informazioni. Quindi dovremmo usare il vecchio modo di aggiornarlo? (ie) ottenere e salvare?

@learning bene amico, tutto dipende dal tuo scenario. Il updatemetodo è ottimo per gli aggiornamenti di massa, ma dovrebbe attivarti un avvertimento nella tua testa quando lo usi per rivedere qualsiasi segnale collegato a quell'oggetto che potrebbe anche essere necessario sparare manualmente
DMac the Destroyer

3
È possibile accedere all'istanza del modello corrente nella funzione di aggiornamento? comeMyModel.objects.filter(pk=some_value).update(field1=self.data)
Dipak,

8
@DipakChandranP Dovresti porre una nuova domanda piuttosto che fare commenti su una di sei anni. Ma le espressioni F () sono probabilmente quelle che desideri.
Daniel Roseman,

70

Gli oggetti del database Django usano lo stesso metodo save () per creare e modificare oggetti.

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

Come Django sa AGGIORNARE vs. INSERIRE
Se l'attributo chiave primaria dell'oggetto è impostato su un valore che viene valutato su Vero (ovvero, un valore diverso da Nessuno o la stringa vuota), Django esegue un AGGIORNAMENTO. Se l'attributo chiave primaria dell'oggetto non è impostato o se UPDATE non ha aggiornato nulla, Django esegue un INSERT.

Rif .: https://docs.djangoproject.com/en/1.9/ref/models/instances/


17

Questa risposta confronta i due approcci precedenti. Se vuoi aggiornare molti oggetti in una sola riga, scegli:

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

Altrimenti dovresti iterare sul set di query e aggiornare i singoli oggetti:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. L'approccio 1 è più veloce perché esegue solo una query sul database, rispetto all'approccio 2 che esegue query sul database 'n + 1'. (Per n elementi nel set di query)

  2. L'approccio del pugno fa una query db cioè UPDATE, la seconda ne fa due: SELECT e poi UPDATE.

  3. Il compromesso è che, supponiamo di avere dei trigger, come l'aggiornamento updated_ono tali campi correlati, non verrà attivato sull'aggiornamento diretto, ad esempio l'approccio 1.

  4. L'approccio 1 viene utilizzato su un set di query, quindi è possibile aggiornare più oggetti contemporaneamente, non nel caso dell'approccio 2.


Riguardo a 1. - Penso che il risultato della query venga memorizzato nella prima chiamata alla query, quindi in realtà c'è ancora solo una chiamata a DB.
user2340939

2

solo in un caso serializer, puoi aggiornare in modo molto semplice!

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

    my_model_serializer.save()

solo in un caso nelle formcose!

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

Penso che i serializzatori siano di Djanog Rest Framework e non proprio di Django.
Apprendista di codice

1
Sì, comunque Django formè di Django Proper.
Jamil Noyda,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.