diff --git a/django/db/models/query.py b/django/db/models/query.py index edb0991e2c..7d41fe1ca6 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -619,8 +619,19 @@ class QuerySet(object): with data aggregated from related fields. """ for arg in args: + if arg.default_alias in kwargs: + raise ValueError("The %s named annotation conflicts with the " + "default name for another annotation." + % arg.default_alias) kwargs[arg.default_alias] = arg + names = set([f.name for f in self.model._meta.fields]) + for aggregate in kwargs: + if aggregate in names: + raise ValueError("The %s annotation conflicts with a field on " + "the model." % aggregate) + + obj = self._clone() obj._setup_aggregate_query(kwargs.keys()) diff --git a/tests/regressiontests/aggregation_regress/tests.py b/tests/regressiontests/aggregation_regress/tests.py index 51f439c5a1..786431420d 100644 --- a/tests/regressiontests/aggregation_regress/tests.py +++ b/tests/regressiontests/aggregation_regress/tests.py @@ -481,6 +481,14 @@ class AggregationTests(TestCase): lambda b: b.name ) + def test_duplicate_alias(self): + # Regression for #11256 - duplicating a default alias raises ValueError. + self.assertRaises(ValueError, Book.objects.all().annotate, Avg('authors__age'), authors__age__avg=Avg('authors__age')) + + def test_field_name_conflict(self): + # Regression for #11256 - providing an aggregate name that conflicts with a field name on the model raises ValueError + self.assertRaises(ValueError, Author.objects.annotate, age=Avg('friends__age')) + def test_pickle(self): # Regression for #10197 -- Queries with aggregates can be pickled. # First check that pickling is possible at all. No crash = success