Actualización masiva en Django
En Django, por defecto, cada modelo tiene un administrador de object
. Este administrador puede hacer muchas cosas, como buscar instancias de modelo, filtrar instancias de modelo, eliminar instancias de modelo. Incluso podemos crear nuestro propio administrador heredando el administrador base proporcionado por Django.
Ahora, cada consulta que aplicamos, como recuperar una única instancia de modelo usando la función get()
o filtrar instancias usando el método filter()
, llega a la base de datos una vez. Esto significa que si tenemos cinco sentencias get()
como sigue, la base de datos será consultada cinco veces 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)
Este es un enfoque ineficiente porque estamos atacando la base de datos individualmente para una sola tarea. Si tenemos que consultar muchas instancias o actualizar muchas instancias para algunos modelos, este enfoque puede ralentizar nuestra aplicación drásticamente.
Para resolver este problema, Django tiene una función incorporada que se puede usar para actualizar múltiples instancias en una consulta, generalmente.
Método bulk_update()
en Django
El método bulk_update
tiene tres parámetros, a saber, objs
, fields
y batch_size
.
objs
: una lista de operaciones a realizarfileds
: una lista de los campos en los que se deben realizar las consultasbatch_size
: el número de objetos que se guardarán en una sola consulta de base de datos. Es un argumento opcional. De forma predeterminada, todos los objetos se actualizan y guardan.
Considere un ejemplo. Supongamos que tenemos un modelo Person
y tenemos que incrementar la edad de todas las personas en 1
utilizando el método bulk_update()
. Haríamos lo siguiente.
En 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)
En views.py
:
people = Person.objects.all()
for person in people:
person.age += 1
Person.objects.bulk_update(people, update_fields=["age"])
Esta operación actualizará la edad de todas las personas en una sola consulta lo cual es muy eficiente.
Inconvenientes del método bulk_update()
El método bulk_update()
es excelente, pero no todo el brillo es oro. Este método tiene algunos inconvenientes.
- Usando el método
bulk_update()
, no podemos actualizar las claves primarias de las instancias. - Cada modelo tiene un método
save()
. Este método no se llama cuando se usa el métodobulk_update()
. - Tenemos que mencionar un tamaño de lote si estamos actualizando muchas columnas para muchos registros. De lo contrario, la consulta SQL generada será muy larga.