Opened 5 years ago

Closed 5 years ago

#25486 closed Bug (duplicate)

ORM generating incorrect query for through-model on <RelatedManager>.all()

Reported by: Arthur Pemberton Owned by: nobody
Component: Database layer (models, ORM) Version: 1.8
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 (last modified by Tim Graham)

I have a through-model which itself has a through model (because it needs a many-to-many relationship). The problem comes when i try to get related mode through this many-to-many relationship. The ORM generates the WHERE clause on the wrong field (the pk, instead of the fk).

-- generated sql
SELECT "core_role"."id", "core_role"."name"
FROM "core_role"
INNER JOIN "core_dealercontactrole" ON ( "core_role"."id" = "core_dealercontactrole"."role_id" )
WHERE "core_dealercontactrole"."id" = 8743
ORDER BY "core_role"."name" ASC

-- corrected sql
SELECT "core_role"."id", "core_role"."name"
FROM "core_role"
INNER JOIN "core_dealercontactrole" ON ( "core_role"."id" = "core_dealercontactrole"."role_id" )
WHERE "core_dealercontactrole"."dealercontact_id" = 8743
ORDER BY "core_role"."name" ASC

The code that generated the query:

dc = DealerContact.objects.get(id=8743)
>>> unicode(dc.roles.all().query)
u'SELECT "core_role"."id", "core_role"."name" FROM "core_role" INNER JOIN "core_dealercontactrole" ON ( "core_role"."id" = "core_dealercontactrole"."role_id" ) WHERE "core_dealercontactrole"."id" = 8743 ORDER BY "core_role"."name" ASC'

Here are the models (with superfluous fields removed):

class Contact(models.Model):
    first_name = models.CharField(blank=True, max_length=50)
    last_name = models.CharField(blank=True, max_length=50)

    class Meta:
        ordering = ('last_name', 'first_name')

class Dealer(models.Model):
    contacts = models.ManyToManyField('Contact', through='DealerContact', related_name='dealers')
    name = models.CharField(db_index=True, max_length=250)

class DealerContact(models.Model):
    dealer = models.ForeignKey('Dealer', related_name='dealercontacts+', on_delete=models.CASCADE)
    contact = models.ForeignKey('Contact', related_name='+', on_delete=models.CASCADE)
    roles = models.ManyToManyField('Role', through='DealerContactRole', related_name='+')

    class Meta:
        unique_together = ('dealer', 'contact')

class DealerContactRole(models.Model):
    dealercontact = models.ForeignKey('DealerContact', related_name='+', on_delete=models.CASCADE)
    role = models.ForeignKey('Role', related_name='+')

    class Meta:
        unique_together = ('dealercontact', 'role')

class Role(models.Model):
    name = models.CharField(db_index=True, max_length=100)

    class Meta:
        ordering = ('name',)

Change History (1)

comment:1 Changed 5 years ago by Tim Graham

Description: modified (diff)
Resolution: duplicate
Status: newclosed

This seems to be a regression in 1.8 and a duplicate of #24505 (bisected to fb48eb05816b1ac87d58696cdfe48be18c901f16 and fixed subsequently fixed in 4ee08958f154594b538207a53c1d457687b3f7ae). I'll backport that fix to 1.8.

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