#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.

Reply via email to