Pasó por las respuestas ya publicadas. Solo pensé que sería mejor si agrego una respuesta con un ejemplo real.
Digamos que tienes 3 modelos de Django que están relacionados.
class M1(models.Model):
name = models.CharField(max_length=10)
class M2(models.Model):
name = models.CharField(max_length=10)
select_relation = models.ForeignKey(M1, on_delete=models.CASCADE)
prefetch_relation = models.ManyToManyField(to='M3')
class M3(models.Model):
name = models.CharField(max_length=10)
Aquí puede consultar el M2
modelo y sus M1
objetos relativos usando el select_relation
campo y los M3
objetos usando el prefetch_relation
campo.
Sin embargo, como hemos mencionado M1
, la relación de M2
es a ForeignKey
, solo devuelve 1 registro para cualquier M2
objeto. Lo mismo se aplica OneToOneField
también.
Pero M3
la relación de M2
es una ManyToManyField
que podría devolver cualquier número de M1
objetos.
Considere un caso en el que tiene 2 M2
objetos m21
, m22
que tienen los mismos 5M3
objetos asociados con ID 1,2,3,4,5
. Cuando busca M3
objetos asociados para cada uno de esos M2
objetos, si usa select related, así es como funcionará.
Pasos:
- Encuentra
m21
objeto.
- Consulta todos los
M3
objetos relacionados con el m21
objeto cuyos ID son 1,2,3,4,5
.
- Repita lo mismo para el
m22
objeto y todos los demás M2
objetos.
Como tenemos mismas 1,2,3,4,5
identificaciones tanto m21
, m22
los objetos, si utilizamos la opción select_related, que va a consultar la base de datos dos veces por los mismos identificadores que ya eran descabellada.
En cambio, si usa prefetch_related, cuando intente obtener M2
objetos, tomará nota de todos los ID que devolvieron sus objetos (Nota: solo los ID) al consultar la M2
tabla y, como último paso, Django hará una consulta a la M3
tabla con el conjunto de todas las ID que sus M2
objetos han devuelto. y unirlos a M2
objetos usando Python en lugar de la base de datos.
De esta manera, está consultando todos los M3
objetos solo una vez, lo que mejora el rendimiento.