#15200: ManyToManyField combined with "|" leads to trouble
---------------------------+------------------------------------------------
 Reporter:  vanschelven    |          Owner:  nobody    
   Status:  new            |      Milestone:            
Component:  Uncategorized  |        Version:  1.2       
 Keywords:                 |   Triage Stage:  Unreviewed
Has patch:  0              |  
---------------------------+------------------------------------------------
 !ManyToManyField combined with "|" leads to trouble.

 Specifically, the outer join that appears to be constructed for manytomany
 field lookups is not well cleaned up with where statements once an "or"
 ("|") is used.

 {{{
 $ cat theapp/models.py
 from django.db import models

 class AnObject(models.Model):
     nr = models.IntegerField()

 class HasRef(models.Model):
     obj = models.ManyToManyField(AnObject)
     field = models.IntegerField()
 }}}

 {{{
 >>> from theapp.models import *
 >>> one = AnObject.objects.create(nr=1)
 >>> two = AnObject.objects.create(nr=2)
 >>> reffer = HasRef.objects.create(field=1)
 >>> reffer.obj.add(one)
 >>> reffer.obj.add(two)
 >>> HasRef.objects.all().filter(field=1)
 [<HasRef: HasRef object>]
 >>> HasRef.objects.all().filter(obj=one)
 [<HasRef: HasRef object>]
 >>> HasRef.objects.all().filter(models.Q(field=1) | models.Q(obj=one))
 [<HasRef: HasRef object>, <HasRef: HasRef object>]
 >>> [o.pk for o in HasRef.objects.all().filter(models.Q(field=1) |
 models.Q(obj=one))]
 [1L, 1L]
 }}}

 I don't have the time right now to come up with tests proper, or a patch.
 The problem is real though...

 My workaround:

 {{{
 >>> HasRef.objects.all().filter(models.Q(field=1) |
 models.Q(obj=one)).annotate(models.Count("id"))
 }}}

 The generated query (without workaround)
 {{{
 >>> print HasRef.objects.all().filter(models.Q(field=1) |
 models.Q(obj=AnObject.objects.get(nr=1))).query
 SELECT `theapp_hasref`.`id`, `theapp_hasref`.`field` FROM `theapp_hasref`
 LEFT OUTER JOIN `theapp_hasref_obj` ON (`theapp_hasref`.`id` =
 `theapp_hasref_obj`.`hasref_id`) WHERE (`theapp_hasref`.`field` = 1  OR
 `theapp_hasref_obj`.`anobject_id` = 1 )
 }}}
 {{{

-- 
Ticket URL: <http://code.djangoproject.com/ticket/15200>
Django <http://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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to