Opened 9 years ago
Closed 9 years ago
#25545 closed Bug (duplicate)
The ORM generates incorrect queries for m2m with disabled backward relations
Reported by: | Morgan Aubert | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Normal | Keywords: | m2m, related_name |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
This bug appears on the latest Django 1.8.5 release if you set two ManyToMany fields with the same name on two distinct models. The ManyToMany relations must be pointing toward the same model.
from django.db import models class TestLabel(models.Model): label = models.CharField(max_length=100) class TestModelA(models.Model): labels = models.ManyToManyField(TestLabel, related_name='a_labels+') class TestModelB(models.Model): labels = models.ManyToManyField(TestLabel, related_name='b_labels+')
Whan you add a TestLabel instance to one of the labels relations, it is correctly added but you cannot fetch it using the all() method of the ManyRelatedManager: an empty list is returned.
>>> t1 = TestLabel.objects.create(label='Test 1') >>> t2 = TestLabel.objects.create(label='Test 2') >>> >>> a = TestModelA.objects.create() >>> b = TestModelB.objects.create() >>> >>> a.labels.add(t1) >>> a.labels.all() []
Moreover, the generated SQL query is incorrect :
>>> print(a.labels.all().query) SELECT "example_project_testlabel"."id", "example_project_testlabel"."label" FROM "example_project_testlabel" INNER JOIN "example_project_testmodelb_labels" ON ( "example_project_testlabel"."id" = "example_project_testmodelb_labels"."testlabel_id" ) WHERE "example_project_testmodelb_labels"."testmodelb_id" = 4
The bug seems to be caused by the related_name which is generated when the backward relation is disabled (0e2d3b93043676975aa921a70b5faafef02cac5c). The related_name should be generated from the name of the relation and the name of the class (this add been fixed in Django 1.9 - see f7b297815819153b53dc1125d3f42869fb1b7ebc).
This bug can cause ValueError exceptions to be raised if prefetch_related is applied to a queryset :
>>> TestModelA.objects.all().prefetch_related('labels') [...] ValueError: Cannot query "TestModelA object": Must be "TestModelB" instance.
Change History (3)
follow-up: 2 comment:1 by , 9 years ago
comment:2 by , 9 years ago
Replying to timgraham:
This is a regression in Django 1.8.5 then?
It seems so. I cannot reproduce the bug by using Django 1.8.4.
comment:3 by , 9 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Marking as duplicate of #24156 and backported that fix to stable/1.8.x in eb85e6672aeb00c67a3666785965edeceed976af. Thanks for the report.
This is a regression in Django 1.8.5 then?