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 M2
modelo e seus M1
objetos relativos usando select_relation
campo e M3
objetos usando prefetch_relation
campo.
No entanto, como mencionamos M1
a relação de M2
é a ForeignKey
, ela retorna apenas 1 registro para qualquer M2
objeto. O mesmo se aplica OneToOneField
também.
Mas M3
a relação de M2
é uma ManyToManyField
que pode retornar qualquer número de M1
objetos.
Considere um caso em que você tem 2 M2
objetos m21
, m22
que possuem os mesmos 5M3
objetos associados aos IDs 1,2,3,4,5
. Quando você busca M3
objetos associados para cada um desses M2
objetos, se você usa o select related, é assim que funciona.
Passos:
- Encontre um
m21
objeto.
- Consulta todos os
M3
objetos relacionados ao m21
objeto cujos IDs são 1,2,3,4,5
.
- Repita a mesma coisa para o
m22
objeto e todos os outros M2
objetos.
Como temos os mesmos 1,2,3,4,5
IDs para ambos m21
, m22
objetos, 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 M2
objetos, ele anotará todos os IDs que seus objetos retornaram (Nota: apenas os IDs) enquanto consultava a M2
tabela e, como último passo, o Django fará uma consulta à M3
tabela com o conjunto de todos os IDs que seus M2
objetos retornaram. e junte-os a M2
objetos usando Python em vez de banco de dados.
Dessa forma, você está consultando todos os M3
objetos apenas uma vez, o que melhora o desempenho.