Passou pelas respostas já postadas. Apenas pensei que seria melhor se eu adicionar uma resposta com exemplo real.
Digamos que você tenha 3 modelos de Django 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)
Aqui você pode consultar o M2modelo e seus M1objetos relativos usando select_relationcampo e M3objetos usando prefetch_relationcampo.
No entanto, como mencionamos M1a relação de M2é a ForeignKey, ela retorna apenas 1 registro para qualquer M2objeto. O mesmo se aplica OneToOneFieldtambém.
Mas M3a relação de M2é uma ManyToManyFieldque pode retornar qualquer número de M1objetos.
Considere um caso em que você tem 2 M2objetos m21, m22que possuem os mesmos 5M3 objetos associados aos IDs 1,2,3,4,5. Quando você busca M3objetos associados para cada um desses M2objetos, se você usa o select related, é assim que funciona.
Passos:
- Encontre um
m21objeto.
- Consulta todos os
M3objetos relacionados ao m21objeto cujos IDs são 1,2,3,4,5.
- Repita a mesma coisa para o
m22objeto e todos os outros M2objetos.
Como temos os mesmos 1,2,3,4,5IDs para ambos m21, m22objetos, se usarmos a opção select_related, ele consultará o banco de dados duas vezes pelos mesmos IDs que já foram buscados.
Em vez disso, se você usar prefetch_related, ao tentar obter M2objetos, ele anotará todos os IDs que seus objetos retornaram (Nota: apenas os IDs) enquanto consultava a M2tabela e, como último passo, o Django fará uma consulta à M3tabela com o conjunto de todos os IDs que seus M2objetos retornaram. e junte-os a M2objetos usando Python em vez de banco de dados.
Dessa forma, você está consultando todos os M3objetos apenas uma vez, o que melhora o desempenho.