#25545: The ORM generates incorrect queries for m2m with disabled backward
relations
----------------------------------------------+----------------------------
Reporter: ellmetha | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.8
Severity: Normal | Keywords: m2m,
| related_name
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+----------------------------
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.
{{{
#!python
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.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25545>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.cd0180f9d3ed944206fd8758a7902fdb%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.