[1.6.x] Fixed #21150 -- Improved Query.add_fields() join promotion logic

Thanks to Eivind Fonn for the report and test case.
This commit is contained in:
Anssi Kääriäinen 2013-09-24 18:42:40 +03:00
parent d30d66b907
commit 1a922870ea
3 changed files with 31 additions and 3 deletions

View File

@ -1525,7 +1525,7 @@ class Query(object):
for name in field_names: for name in field_names:
field, targets, u2, joins, path = self.setup_joins( field, targets, u2, joins, path = self.setup_joins(
name.split(LOOKUP_SEP), opts, alias, None, allow_m2m, name.split(LOOKUP_SEP), opts, alias, None, allow_m2m,
True) allow_explicit_fk=True, outer_if_first=True)
# Trim last join if possible # Trim last join if possible
targets, final_alias, remaining_joins = self.trim_joins(targets, joins[-2:], path) targets, final_alias, remaining_joins = self.trim_joins(targets, joins[-2:], path)

View File

@ -87,3 +87,14 @@ class HardbackBook(Book):
def __str__(self): def __str__(self):
return "%s (hardback): %s" % (self.name, self.weight) return "%s (hardback): %s" % (self.name, self.weight)
# Models for ticket #21150
class Alfa(models.Model):
pass
class Bravo(models.Model):
pass
class Charlie(models.Model):
alfa = models.ForeignKey(Alfa, null=True)
bravo = models.ForeignKey(Bravo, null=True)

View File

@ -12,8 +12,9 @@ from django.test import TestCase, Approximate, skipUnlessDBFeature
from django.utils import six from django.utils import six
from django.utils.unittest import expectedFailure from django.utils.unittest import expectedFailure
from .models import (Author, Book, Publisher, Clues, Entries, HardbackBook, from .models import (
ItemTag, WithManualPK) Author, Book, Publisher, Clues, Entries, HardbackBook, ItemTag,
WithManualPK, Alfa, Bravo, Charlie)
class AggregationTests(TestCase): class AggregationTests(TestCase):
@ -1107,3 +1108,19 @@ class AggregationTests(TestCase):
self.assertQuerysetEqual( self.assertQuerysetEqual(
qs, ['Sams Teach Yourself Django in 24 Hours'], qs, ['Sams Teach Yourself Django in 24 Hours'],
lambda b: b.name) lambda b: b.name)
def test_ticket_21150(self):
b = Bravo.objects.create()
c = Charlie.objects.create(bravo=b)
qs = Charlie.objects.select_related('alfa').annotate(Count('bravo__charlie'))
self.assertQuerysetEqual(
qs, [c], lambda x: x)
self.assertIs(qs[0].alfa, None)
a = Alfa.objects.create()
c.alfa = a
c.save()
# Force re-evaluation
qs = qs.all()
self.assertQuerysetEqual(
qs, [c], lambda x: x)
self.assertEqual(qs[0].alfa, a)