Opened 12 years ago
Closed 12 years ago
#20062 closed Bug (invalid)
Filtering ManyToManyField in a class with OneToOneField as a primary key generates a wrong query
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When I have the following models:
class Produto(models.Model): nome = models.CharField(max_length=200) class Variacao(models.Model): nome = models.CharField(max_length=200) class ItemVariacao(models.Model): variacao = models.ForeignKey(Variacao) nome = models.CharField(max_length=200) class ProdutoVariacao(models.Model): produto = models.OneToOneField(Produto, primary_key=True) variacoes = models.ManyToManyField(ItemVariacao)
and execute this:
Variacao.objects.filter(itemvariacao__produtovariacao__produto__in=[1,2]).query
django generates it:
SELECT "produto_variacao"."id", "produto_variacao"."nome" FROM "produto_variacao" INNER JOIN "produto_itemvariacao" ON ("produto_variacao"."id" = "produto_itemvariacao"."variacao_id") INNER JOIN "produto_produtovariacao_variacoes" ON ("produto_itemvariacao"."id" = "produto_produtovariacao_variacoes"."itemvariacao_id") WHERE "produto_produtovariacao_variacoes"."produtovariacao_id" IN (1, 2) ORDER BY "produto_variacao"."nome" ASC
instead of:
SELECT "produto_variacao"."id", "produto_variacao"."nome" FROM "produto_variacao" INNER JOIN "produto_itemvariacao" ON ("produto_variacao"."id" = "produto_itemvariacao"."variacao_id") INNER JOIN "produto_produtovariacao_variacoes" ON ("produto_itemvariacao"."id" = "produto_produtovariacao_variacoes"."itemvariacao_id") INNER JOIN "produto_produtovariacao" ON ("produto_produtovariacao_variacoes"."produtovariacao_id" = "produto_produtovariacao"."id") WHERE "produto_produtovariacao"."produto_id" IN (1, 2) ORDER BY "produto_variacao"."nome" ASC
I removed primary_key attribute from OneToOneField to test using id as primary key and django generated query properly as in second example.
Note:
See TracTickets
for help on using tickets.
If I am reading this correctly then Django is actually doing the correct thing here. "produto_produtovariacao_variacoes"."produtovariacao_id" is guaranteed to have the same value as produto_produtovariacao.produto_id (foreign key from produtovariacao_id to the primary key produto_id), so the last join can be trimmed. When you remove the primary key, then the foreign key is to id instead of produto_id, and thus the last join can't be trimmed any more.