Ticket #11535: generic_relations_or.diff
File generic_relations_or.diff, 5.1 KB (added by , 15 years ago) |
---|
-
django/db/models/sql/query.py
diff -r d0dc9aaff6af django/db/models/sql/query.py
a b 1670 1670 for child in q_object.children: 1671 1671 if connector == OR: 1672 1672 refcounts_before = self.alias_refcount.copy() 1673 # a subtree may also be necesary for add_filter, in the 1674 # case where extra_filters is a non-empty list 1675 self.where.start_subtree(connector) 1673 1676 if isinstance(child, Node): 1674 self.where.start_subtree(connector)1675 1677 self.add_q(child, used_aliases) 1676 self.where.end_subtree()1677 1678 else: 1678 1679 self.add_filter(child, connector, q_object.negated, 1679 1680 can_reuse=used_aliases) 1681 self.where.end_subtree() 1680 1682 if connector == OR: 1681 1683 # Aliases that were newly added or not used at all need to 1682 1684 # be promoted to outer joins if they are nullable relations. -
tests/regressiontests/generic_relations_regress/models.py
diff -r d0dc9aaff6af tests/regressiontests/generic_relations_regress/models.py
a b 2 2 from django.contrib.contenttypes import generic 3 3 from django.contrib.contenttypes.models import ContentType 4 4 5 __all__ = ('Link', 'Place', 'Restaurant', 'Contact', 'Organization', 'Note') 6 7 5 8 class Link(models.Model): 9 6 10 content_type = models.ForeignKey(ContentType) 7 11 object_id = models.PositiveIntegerField() 8 12 content_object = generic.GenericForeignKey() … … 10 14 def __unicode__(self): 11 15 return "Link to %s id=%s" % (self.content_type, self.object_id) 12 16 17 13 18 class Place(models.Model): 19 14 20 name = models.CharField(max_length=100) 15 21 links = generic.GenericRelation(Link) 16 22 17 23 def __unicode__(self): 18 24 return "Place: %s" % self.name 19 20 class Restaurant(Place): 25 26 27 class Restaurant(Place): 28 21 29 def __unicode__(self): 22 return "Restaurant: %s" % self.name 23 No newline at end of file 30 return "Restaurant: %s" % self.name 31 32 33 # models for test_q_object_or: 34 class Note(models.Model): 35 36 content_type = models.ForeignKey(ContentType) 37 object_id = models.PositiveIntegerField() 38 content_object = generic.GenericForeignKey() 39 note = models.TextField() 40 41 42 class Contact(models.Model): 43 44 notes = generic.GenericRelation(Note) 45 46 47 class Organization(models.Model): 48 49 name = models.CharField(max_length=255) 50 contacts = models.ManyToManyField(Contact, related_name='organizations') -
tests/regressiontests/generic_relations_regress/tests.py
diff -r d0dc9aaff6af tests/regressiontests/generic_relations_regress/tests.py
a b 1 1 from django.test import TestCase 2 2 from django.contrib.contenttypes.models import ContentType 3 from models import Link, Place, Restaurant 3 from models import * 4 from django.db.models import Q 5 4 6 5 7 class GenericRelationTests(TestCase): 6 8 7 9 def test_inherited_models_content_type(self): 8 10 """ 9 11 Test that GenericRelations on inherited classes use the correct content 10 12 type. 11 13 """ 12 14 13 15 p = Place.objects.create(name="South Park") 14 r = Restaurant.objects.create(name="Chubby's") 16 r = Restaurant.objects.create(name="Chubby's") 15 17 l1 = Link.objects.create(content_object=p) 16 18 l2 = Link.objects.create(content_object=r) 17 19 self.assertEqual(list(p.links.all()), [l1]) 18 20 self.assertEqual(list(r.links.all()), [l2]) 19 20 No newline at end of file 21 22 def test_q_object_or(self): 23 """ 24 Tests that SQL query parameters for generic relations are properly 25 grouped when OR is used. 26 27 Test for bug http://code.djangoproject.com/ticket/11535 28 29 In this bug the first query (below) works while the second, with the 30 query parameters the same but in reverse order, does not. 31 32 The issue is that the generic relation conditions do not get properly 33 grouped in parentheses. 34 """ 35 note_contact = Contact.objects.create() 36 org_contact = Contact.objects.create() 37 note = Note.objects.create(note='note', content_object=note_contact) 38 org = Organization.objects.create(name='org name') 39 org.contacts.add(org_contact) 40 # search with a non-matching note and a matching org name 41 qs = Contact.objects.filter(Q(notes__note__icontains=r'other note') | 42 Q(organizations__name__icontains=r'org name')) 43 self.assertTrue(org_contact in qs) 44 # search again, with the same query parameters, in reverse order 45 qs = Contact.objects.filter( 46 Q(organizations__name__icontains=r'org name') | 47 Q(notes__note__icontains=r'other note')) 48 self.assertTrue(org_contact in qs)