Opened 2 years ago

Closed 2 years ago

#20062 closed Bug (invalid)

Filtering ManyToManyField in a class with OneToOneField as a primary key generates a wrong query

Reported by: alexandre@… 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.

Change History (1)

comment:1 Changed 2 years ago by akaariai

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

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.

Note: See TracTickets for help on using tickets.
Back to Top