Skip to content

Commit d450af8

Browse files
committed
Fixed small inconsistency when handling aggregate's default_alias.
Refs django#14030.
1 parent 039465a commit d450af8

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

django/db/models/query.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,13 @@ def aggregate(self, *args, **kwargs):
288288
if self.query.distinct_fields:
289289
raise NotImplementedError("aggregate() + distinct(fields) not implemented.")
290290
for arg in args:
291-
if not hasattr(arg, 'default_alias'):
291+
# The default_alias property may raise a TypeError, so we use
292+
# a try/except construct rather than hasattr in order to remain
293+
# consistent between PY2 and PY3 (hasattr would swallow
294+
# the TypeError on PY2).
295+
try:
296+
arg.default_alias
297+
except (AttributeError, TypeError):
292298
raise TypeError("Complex aggregates require an alias")
293299
kwargs[arg.default_alias] = arg
294300

@@ -759,14 +765,16 @@ def annotate(self, *args, **kwargs):
759765
"""
760766
annotations = OrderedDict() # To preserve ordering of args
761767
for arg in args:
768+
# The default_alias property may raise a TypeError, so we use
769+
# a try/except construct rather than hasattr in order to remain
770+
# consistent between PY2 and PY3 (hasattr would swallow
771+
# the TypeError on PY2).
762772
try:
763-
# we can't do an hasattr here because py2 returns False
764-
# if default_alias exists but throws a TypeError
765773
if arg.default_alias in kwargs:
766774
raise ValueError("The named annotation '%s' conflicts with the "
767775
"default name for another annotation."
768776
% arg.default_alias)
769-
except AttributeError: # default_alias
777+
except (AttributeError, TypeError):
770778
raise TypeError("Complex annotations require an alias")
771779
annotations[arg.default_alias] = arg
772780
annotations.update(kwargs)

tests/aggregation/tests.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,10 +768,12 @@ def test_combine_different_types(self):
768768
self.assertEqual(b3.sums, Approximate(Decimal("383.69"), places=2))
769769

770770
def test_complex_aggregations_require_kwarg(self):
771-
with six.assertRaisesRegex(self, TypeError, 'Complex expressions require an alias'):
771+
with six.assertRaisesRegex(self, TypeError, 'Complex annotations require an alias'):
772772
Author.objects.annotate(Sum(F('age') + F('friends__age')))
773773
with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'):
774774
Author.objects.aggregate(Sum('age') / Count('age'))
775+
with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'):
776+
Author.objects.aggregate(Sum(Value(1)))
775777

776778
def test_aggregate_over_complex_annotation(self):
777779
qs = Author.objects.annotate(

0 commit comments

Comments
 (0)