diff options
| author | Alexandr Tatarinov <tatarinov1997@gmail.com> | 2020-06-14 21:38:43 +0300 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-07-31 13:19:33 +0200 |
| commit | f4ac167119e8897c398527c392ed117326496652 (patch) | |
| tree | 7df0826447759a792c008286314bc3477405d33d /django/db/models/sql/query.py | |
| parent | 88af11c58baf0eae2fa947a5f0733906ffe6bb38 (diff) | |
Fixed #27719 -- Added QuerySet.alias() to allow creating reusable aliases.
QuerySet.alias() allows creating reusable aliases for expressions that
don't need to be selected but are used for filtering, ordering, or as
a part of complex expressions.
Thanks Simon Charette for reviews.
Diffstat (limited to 'django/db/models/sql/query.py')
| -rw-r--r-- | django/db/models/sql/query.py | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index b53980a68f..659fa87314 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1015,11 +1015,14 @@ class Query(BaseExpression): alias = seen[int_model] = join_info.joins[-1] return alias or seen[None] - def add_annotation(self, annotation, alias, is_summary=False): + def add_annotation(self, annotation, alias, is_summary=False, select=True): """Add a single annotation expression to the Query.""" annotation = annotation.resolve_expression(self, allow_joins=True, reuse=None, summarize=is_summary) - self.append_annotation_mask([alias]) + if select: + self.append_annotation_mask([alias]) + else: + self.set_annotation_mask(set(self.annotation_select).difference({alias})) self.annotations[alias] = annotation def resolve_expression(self, query, *args, **kwargs): @@ -1707,6 +1710,11 @@ class Query(BaseExpression): # which is executed as a wrapped subquery if any of the # aggregate() elements reference an existing annotation. In # that case we need to return a Ref to the subquery's annotation. + if name not in self.annotation_select: + raise FieldError( + "Cannot aggregate over the '%s' alias. Use annotate() " + "to promote it." % name + ) return Ref(name, self.annotation_select[name]) else: return annotation @@ -1911,6 +1919,11 @@ class Query(BaseExpression): # For lookups spanning over relationships, show the error # from the model on which the lookup failed. raise + elif name in self.annotations: + raise FieldError( + "Cannot select the '%s' alias. Use annotate() to promote " + "it." % name + ) else: names = sorted([ *get_field_names_from_opts(opts), *self.extra, |
