Aggiornamento collettivo in Django
In Django, per impostazione predefinita, ogni modello ha un gestore di objects
. Questo gestore può fare molte cose come recuperare le istanze del modello, filtrare le istanze del modello, eliminare le istanze del modello. Possiamo persino creare il nostro gestore ereditando il gestore di base fornito da Django.
Ora, ogni singola query che applichiamo, come il recupero di una singola istanza del modello utilizzando la funzione get()
o il filtraggio delle istanze utilizzando il metodo filter()
, colpisce il database una volta. Ciò significa che se abbiamo cinque istruzioni get()
come segue, il database verrà interrogato cinque volte individualmente.
person = Person.objects.get(id=1)
person = Person.objects.get(id=2)
person = Person.objects.get(id=3)
person = Person.objects.get(id=4)
person = Person.objects.get(id=5)
Questo è un approccio inefficiente perché stiamo colpendo il database individualmente per una singola attività. Se dobbiamo interrogare molte istanze o aggiornare molte istanze per alcuni modelli, questo approccio può rallentare notevolmente la nostra applicazione.
Per risolvere questo problema, Django ha una funzione integrata che può essere utilizzata per aggiornare più istanze in una query, in genere.
Metodo bulk_update()
in Django
Il metodo bulk_update
ha tre parametri, vale a dire objs
, fields
e batch_size
.
objs
- Un elenco di operazioni da eseguirefields
- Un elenco di campi su cui devono essere eseguite le querybatch_size
- Il numero di oggetti da salvare in una singola query del database. È un argomento facoltativo. Per impostazione predefinita, tutti gli oggetti vengono aggiornati e salvati.
Considera un esempio. Supponiamo di avere un modello Person
e di dover incrementare l’età di tutte le persone di 1
usando il metodo bulk_update()
. Faremmo quanto segue.
In models.py
:
from django.db import models
class Person(models.Model):
username = models.CharField(max_length=200, unique=True)
firstName = models.CharField(max_length=200)
middleName = models.CharField(max_length=200)
lastName = models.CharField(max_length=200)
age = models.IntegerField(default=0)
In views.py
:
people = Person.objects.all()
for person in people:
person.age += 1
Person.objects.bulk_update(people, update_fields=["age"])
Questa operazione aggiornerà l’età di tutte le persone in un’unica query che è molto efficiente.
Svantaggi del metodo bulk_update()
Il metodo bulk_update()
è eccellente, ma non tutto il luccichio è oro. Questo metodo presenta alcuni inconvenienti.
- Utilizzando il metodo
bulk_update()
, non possiamo aggiornare le chiavi primarie delle istanze. - Ogni modello ha un metodo
save()
. Questo metodo non viene chiamato quando si utilizza il metodobulk_update()
. - Dobbiamo menzionare una dimensione batch se stiamo aggiornando molte colonne per molti record. In caso contrario, la query SQL generata sarà molto lunga.