diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 27c6859c61..99663b646b 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1053,14 +1053,14 @@ class Query(object): value = SQLEvaluator(value, self) having_clause = value.contains_aggregate - if parts[0] in self.aggregates: - aggregate = self.aggregates[parts[0]] - entry = self.where_class() - entry.add((aggregate, lookup_type, value), AND) - if negate: - entry.negate() - self.having.add(entry, connector) - return + for alias, aggregate in self.aggregates.items(): + if alias in (parts[0], LOOKUP_SEP.join(parts)): + entry = self.where_class() + entry.add((aggregate, lookup_type, value), AND) + if negate: + entry.negate() + self.having.add(entry, connector) + return opts = self.get_meta() alias = self.get_initial_alias() diff --git a/tests/regressiontests/aggregation_regress/tests.py b/tests/regressiontests/aggregation_regress/tests.py index 14104210af..15692b6422 100644 --- a/tests/regressiontests/aggregation_regress/tests.py +++ b/tests/regressiontests/aggregation_regress/tests.py @@ -827,3 +827,30 @@ class AggregationTests(TestCase): Book.objects.aggregate(Variance('price', sample=True)), {'price__variance': Approximate(700.53, 2)} ) + + def test_filtering_by_annotation_name(self): + # Regression test for #14476 + + # The name of the explicitly provided annotation name in this case + # poses no problem + qs = Author.objects.annotate(book_cnt=Count('book')).filter(book_cnt=2) + self.assertQuerysetEqual( + qs, + ['Peter Norvig'], + lambda b: b.name + ) + # Neither in this case + qs = Author.objects.annotate(book_count=Count('book')).filter(book_count=2) + self.assertQuerysetEqual( + qs, + ['Peter Norvig'], + lambda b: b.name + ) + # This case used to fail because the ORM couldn't resolve the + # automatically generated annotation name `book__count` + qs = Author.objects.annotate(Count('book')).filter(book__count=2) + self.assertQuerysetEqual( + qs, + ['Peter Norvig'], + lambda b: b.name + )