From 8b040e3cbbb2e81420e777afc3ca48a1c8f4dd5a Mon Sep 17 00:00:00 2001 From: Ian Foote Date: Sun, 15 Nov 2020 22:43:47 +0000 Subject: Fixed #25534, Fixed #31639 -- Added support for transform references in expressions. Thanks Mariusz Felisiak and Simon Charette for reviews. --- django/db/models/sql/query.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'django/db/models/sql') diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index b7f8053cb1..93cc32ac3c 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1610,6 +1610,8 @@ class Query(BaseExpression): # fields to the appropriate wrapped version. def final_transformer(field, alias): + if not self.alias_cols: + alias = None return field.get_col(alias) # Try resolving all the names as fields first. If there's an error, @@ -1714,8 +1716,6 @@ class Query(BaseExpression): yield from (expr.alias for expr in cls._gen_cols(exprs)) def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False): - if not allow_joins and LOOKUP_SEP in name: - raise FieldError("Joined field references are not permitted in this query") annotation = self.annotations.get(name) if annotation is not None: if not allow_joins: @@ -1740,6 +1740,11 @@ class Query(BaseExpression): return annotation else: field_list = name.split(LOOKUP_SEP) + annotation = self.annotations.get(field_list[0]) + if annotation is not None: + for transform in field_list[1:]: + annotation = self.try_transform(annotation, transform) + return annotation join_info = self.setup_joins(field_list, self.get_meta(), self.get_initial_alias(), can_reuse=reuse) targets, final_alias, join_list = self.trim_joins(join_info.targets, join_info.joins, join_info.path) if not allow_joins and len(join_list) > 1: @@ -1749,10 +1754,10 @@ class Query(BaseExpression): "isn't supported") # Verify that the last lookup in name is a field or a transform: # transform_function() raises FieldError if not. - join_info.transform_function(targets[0], final_alias) + transform = join_info.transform_function(targets[0], final_alias) if reuse is not None: reuse.update(join_list) - return self._get_col(targets[0], join_info.targets[0], join_list[-1]) + return transform def split_exclude(self, filter_expr, can_reuse, names_with_path): """ -- cgit v1.3