diff --git a/django/db/models/sql/aggregates.py b/django/db/models/sql/aggregates.py
index aef8b49..ce2968c 100644
a
|
b
|
import copy
|
5 | 5 | |
6 | 6 | from django.db.models.fields import IntegerField, FloatField |
7 | 7 | from django.db.models.lookups import RegisterLookupMixin |
| 8 | from django.utils.functional import cached_property |
8 | 9 | |
9 | 10 | |
10 | 11 | __all__ = ['Aggregate', 'Avg', 'Count', 'Max', 'Min', 'StdDev', 'Sum', 'Variance'] |
11 | 12 | |
12 | 13 | |
13 | | # Fake fields used to identify aggregate types in data-conversion operations. |
14 | | ordinal_aggregate_field = IntegerField() |
15 | | computed_aggregate_field = FloatField() |
16 | | |
17 | | |
18 | 14 | class Aggregate(RegisterLookupMixin): |
19 | 15 | """ |
20 | 16 | Default SQL Aggregate. |
… |
… |
class Aggregate(RegisterLookupMixin):
|
61 | 57 | |
62 | 58 | while tmp and isinstance(tmp, Aggregate): |
63 | 59 | if getattr(tmp, 'is_ordinal', False): |
64 | | tmp = ordinal_aggregate_field |
| 60 | tmp = self._ordinal_aggregate_field |
65 | 61 | elif getattr(tmp, 'is_computed', False): |
66 | | tmp = computed_aggregate_field |
| 62 | tmp = self._computed_aggregate_field |
67 | 63 | else: |
68 | 64 | tmp = tmp.source |
69 | 65 | |
70 | 66 | self.field = tmp |
71 | 67 | |
| 68 | # Two fake fields used to identify aggregate types in data-conversion operations. |
| 69 | @cached_property |
| 70 | def _ordinal_aggregate_field(self): |
| 71 | return IntegerField() |
| 72 | |
| 73 | @cached_property |
| 74 | def _computed_aggregate_field(self): |
| 75 | return FloatField() |
| 76 | |
72 | 77 | def relabeled_clone(self, change_map): |
73 | 78 | clone = copy.copy(self) |
74 | 79 | if isinstance(self.col, (list, tuple)): |