Loading django/db/models/query.py +12 −4 Original line number Diff line number Diff line Loading @@ -288,7 +288,13 @@ class QuerySet(object): if self.query.distinct_fields: raise NotImplementedError("aggregate() + distinct(fields) not implemented.") for arg in args: if not hasattr(arg, 'default_alias'): # The default_alias property may raise a TypeError, so we use # a try/except construct rather than hasattr in order to remain # consistent between PY2 and PY3 (hasattr would swallow # the TypeError on PY2). try: arg.default_alias except (AttributeError, TypeError): raise TypeError("Complex aggregates require an alias") kwargs[arg.default_alias] = arg Loading Loading @@ -759,14 +765,16 @@ class QuerySet(object): """ annotations = OrderedDict() # To preserve ordering of args for arg in args: # The default_alias property may raise a TypeError, so we use # a try/except construct rather than hasattr in order to remain # consistent between PY2 and PY3 (hasattr would swallow # the TypeError on PY2). try: # we can't do an hasattr here because py2 returns False # if default_alias exists but throws a TypeError if arg.default_alias in kwargs: raise ValueError("The named annotation '%s' conflicts with the " "default name for another annotation." % arg.default_alias) except AttributeError: # default_alias except (AttributeError, TypeError): raise TypeError("Complex annotations require an alias") annotations[arg.default_alias] = arg annotations.update(kwargs) Loading tests/aggregation/tests.py +3 −1 Original line number Diff line number Diff line Loading @@ -768,10 +768,12 @@ class ComplexAggregateTestCase(TestCase): self.assertEqual(b3.sums, Approximate(Decimal("383.69"), places=2)) def test_complex_aggregations_require_kwarg(self): with six.assertRaisesRegex(self, TypeError, 'Complex expressions require an alias'): with six.assertRaisesRegex(self, TypeError, 'Complex annotations require an alias'): Author.objects.annotate(Sum(F('age') + F('friends__age'))) with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'): Author.objects.aggregate(Sum('age') / Count('age')) with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'): Author.objects.aggregate(Sum(Value(1))) def test_aggregate_over_complex_annotation(self): qs = Author.objects.annotate( Loading Loading
django/db/models/query.py +12 −4 Original line number Diff line number Diff line Loading @@ -288,7 +288,13 @@ class QuerySet(object): if self.query.distinct_fields: raise NotImplementedError("aggregate() + distinct(fields) not implemented.") for arg in args: if not hasattr(arg, 'default_alias'): # The default_alias property may raise a TypeError, so we use # a try/except construct rather than hasattr in order to remain # consistent between PY2 and PY3 (hasattr would swallow # the TypeError on PY2). try: arg.default_alias except (AttributeError, TypeError): raise TypeError("Complex aggregates require an alias") kwargs[arg.default_alias] = arg Loading Loading @@ -759,14 +765,16 @@ class QuerySet(object): """ annotations = OrderedDict() # To preserve ordering of args for arg in args: # The default_alias property may raise a TypeError, so we use # a try/except construct rather than hasattr in order to remain # consistent between PY2 and PY3 (hasattr would swallow # the TypeError on PY2). try: # we can't do an hasattr here because py2 returns False # if default_alias exists but throws a TypeError if arg.default_alias in kwargs: raise ValueError("The named annotation '%s' conflicts with the " "default name for another annotation." % arg.default_alias) except AttributeError: # default_alias except (AttributeError, TypeError): raise TypeError("Complex annotations require an alias") annotations[arg.default_alias] = arg annotations.update(kwargs) Loading
tests/aggregation/tests.py +3 −1 Original line number Diff line number Diff line Loading @@ -768,10 +768,12 @@ class ComplexAggregateTestCase(TestCase): self.assertEqual(b3.sums, Approximate(Decimal("383.69"), places=2)) def test_complex_aggregations_require_kwarg(self): with six.assertRaisesRegex(self, TypeError, 'Complex expressions require an alias'): with six.assertRaisesRegex(self, TypeError, 'Complex annotations require an alias'): Author.objects.annotate(Sum(F('age') + F('friends__age'))) with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'): Author.objects.aggregate(Sum('age') / Count('age')) with six.assertRaisesRegex(self, TypeError, 'Complex aggregates require an alias'): Author.objects.aggregate(Sum(Value(1))) def test_aggregate_over_complex_annotation(self): qs = Author.objects.annotate( Loading