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 M2modelo y sus M1objetos relativos usando el select_relationcampo y los M3objetos usando el prefetch_relationcampo.
Sin embargo, como hemos mencionado M1, la relación de M2es a ForeignKey, solo devuelve 1 registro para cualquier M2objeto. Lo mismo se aplica OneToOneFieldtambién.
Pero M3la relación de M2es una ManyToManyFieldque podría devolver cualquier número de M1objetos.
Considere un caso en el que tiene 2 M2objetos m21, m22que tienen los mismos 5M3 objetos asociados con ID 1,2,3,4,5. Cuando busca M3objetos asociados para cada uno de esos M2objetos, si usa select related, así es como funcionará.
Pasos:
- Encuentra
m21objeto.
- Consulta todos los
M3objetos relacionados con el m21objeto cuyos ID son 1,2,3,4,5.
- Repita lo mismo para el
m22objeto y todos los demás M2objetos.
Como tenemos mismas 1,2,3,4,5identificaciones tanto m21, m22los 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 M2objetos, tomará nota de todos los ID que devolvieron sus objetos (Nota: solo los ID) al consultar la M2tabla y, como último paso, Django hará una consulta a la M3tabla con el conjunto de todas las ID que sus M2objetos han devuelto. y unirlos a M2objetos usando Python en lugar de la base de datos.
De esta manera, está consultando todos los M3objetos solo una vez, lo que mejora el rendimiento.