Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[1.2.X] Fixed #14707 -- Relax the protections on aggregate naming col…

…lisions when a ValuesQuerySet removes the colliding name. Thanks to Andy McKay for the report.

Backport of r15223 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15224 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit be12f9e2784d8d606fc856d80fadae4e9ca34117 1 parent 73b3611
@freakboy3742 freakboy3742 authored
View
9 django/db/models/query.py
@@ -631,18 +631,19 @@ def annotate(self, *args, **kwargs):
"""
for arg in args:
if arg.default_alias in kwargs:
- raise ValueError("The %s named annotation conflicts with the "
+ raise ValueError("The named annotation '%s' conflicts with the "
"default name for another annotation."
% arg.default_alias)
kwargs[arg.default_alias] = arg
- names = set(self.model._meta.get_all_field_names())
+ names = getattr(self, '_fields', None)
+ if names is None:
+ names = set(self.model._meta.get_all_field_names())
for aggregate in kwargs:
if aggregate in names:
- raise ValueError("The %s annotation conflicts with a field on "
+ raise ValueError("The annotation '%s' conflicts with a field on "
"the model." % aggregate)
-
obj = self._clone()
obj._setup_aggregate_query(kwargs.keys())
View
22 tests/regressiontests/aggregation_regress/tests.py
@@ -495,6 +495,28 @@ def test_m2m_name_conflict(self):
# Regression for #11256 - providing an aggregate name that conflicts with an m2m name on the model raises ValueError
self.assertRaises(ValueError, Author.objects.annotate, friends=Count('friends'))
+ def test_values_queryset_non_conflict(self):
+ # Regression for #14707 -- If you're using a values query set, some potential conflicts are avoided.
+
+ # age is a field on Author, so it shouldn't be allowed as an aggregate.
+ # But age isn't included in the ValuesQuerySet, so it is.
+ results = Author.objects.values('name').annotate(age=Count('book_contact_set'))
+ self.assertEquals(len(results), 9)
+ self.assertEquals(results[0]['name'], u'Adrian Holovaty')
+ self.assertEquals(results[0]['age'], 1)
+
+ # Same problem, but aggregating over m2m fields
+ results = Author.objects.values('name').annotate(age=Avg('friends__age'))
+ self.assertEquals(len(results), 9)
+ self.assertEquals(results[0]['name'], u'Adrian Holovaty')
+ self.assertEquals(results[0]['age'], 32.0)
+
+ # Same problem, but colliding with an m2m field
+ results = Author.objects.values('name').annotate(friends=Count('friends'))
+ self.assertEquals(len(results), 9)
+ self.assertEquals(results[0]['name'], u'Adrian Holovaty')
+ self.assertEquals(results[0]['friends'], 2)
+
def test_reverse_relation_name_conflict(self):
# Regression for #11256 - providing an aggregate name that conflicts with a reverse-related name on the model raises ValueError
self.assertRaises(ValueError, Author.objects.annotate, book_contact_set=Avg('friends__age'))
Please sign in to comment.
Something went wrong with that request. Please try again.