diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 510b21b64b3..45276640e0f 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1525,7 +1525,7 @@ class Query(object): for name in field_names: field, targets, u2, joins, path = self.setup_joins( name.split(LOOKUP_SEP), opts, alias, None, allow_m2m, - True) + allow_explicit_fk=True, outer_if_first=True) # Trim last join if possible targets, final_alias, remaining_joins = self.trim_joins(targets, joins[-2:], path) diff --git a/tests/aggregation_regress/models.py b/tests/aggregation_regress/models.py index dfef691882b..24859f4ce45 100644 --- a/tests/aggregation_regress/models.py +++ b/tests/aggregation_regress/models.py @@ -87,3 +87,14 @@ class HardbackBook(Book): def __str__(self): 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) diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py index 80441b9a608..1f1561351fc 100644 --- a/tests/aggregation_regress/tests.py +++ b/tests/aggregation_regress/tests.py @@ -12,8 +12,9 @@ from django.test import TestCase, Approximate, skipUnlessDBFeature from django.utils import six from django.utils.unittest import expectedFailure -from .models import (Author, Book, Publisher, Clues, Entries, HardbackBook, - ItemTag, WithManualPK) +from .models import ( + Author, Book, Publisher, Clues, Entries, HardbackBook, ItemTag, + WithManualPK, Alfa, Bravo, Charlie) class AggregationTests(TestCase): @@ -1107,3 +1108,19 @@ class AggregationTests(TestCase): self.assertQuerysetEqual( qs, ['Sams Teach Yourself Django in 24 Hours'], 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)