From 2162f0983de0dfe2178531638ce7ea56f54dd4e7 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Sun, 18 Jun 2017 16:53:40 +0100 Subject: Fixed #24747 -- Allowed transforms in QuerySet.order_by() and distinct(*fields). --- django/db/models/sql/compiler.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'django/db/models/sql/compiler.py') diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 1f78a8b5b2..1fdbd156b6 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -451,7 +451,7 @@ class SQLCompiler: raise NotSupportedError('{} is not supported on this database backend.'.format(combinator)) result, params = self.get_combinator_sql(combinator, self.query.combinator_all) else: - distinct_fields = self.get_distinct() + distinct_fields, distinct_params = self.get_distinct() # This must come after 'select', 'ordering', and 'distinct' # (see docstring of get_from_clause() for details). from_, f_params = self.get_from_clause() @@ -461,7 +461,12 @@ class SQLCompiler: params = [] if self.query.distinct: - result.append(self.connection.ops.distinct_sql(distinct_fields)) + distinct_result, distinct_params = self.connection.ops.distinct_sql( + distinct_fields, + distinct_params, + ) + result += distinct_result + params += distinct_params out_cols = [] col_idx = 1 @@ -621,21 +626,22 @@ class SQLCompiler: This method can alter the tables in the query, and thus it must be called before get_from_clause(). """ - qn = self.quote_name_unless_alias - qn2 = self.connection.ops.quote_name result = [] + params = [] opts = self.query.get_meta() for name in self.query.distinct_fields: parts = name.split(LOOKUP_SEP) - _, targets, alias, joins, path, _ = self._setup_joins(parts, opts, None) + _, targets, alias, joins, path, _, transform_function = self._setup_joins(parts, opts, None) targets, alias, _ = self.query.trim_joins(targets, joins, path) for target in targets: if name in self.query.annotation_select: result.append(name) else: - result.append("%s.%s" % (qn(alias), qn2(target.column))) - return result + r, p = self.compile(transform_function(target, alias)) + result.append(r) + params.append(p) + return result, params def find_ordering_name(self, name, opts, alias=None, default_order='ASC', already_seen=None): @@ -647,7 +653,7 @@ class SQLCompiler: name, order = get_order_dir(name, default_order) descending = order == 'DESC' pieces = name.split(LOOKUP_SEP) - field, targets, alias, joins, path, opts = self._setup_joins(pieces, opts, alias) + field, targets, alias, joins, path, opts, transform_function = self._setup_joins(pieces, opts, alias) # If we get to this point and the field is a relation to another model, # append the default ordering for that model unless the attribute name @@ -666,7 +672,7 @@ class SQLCompiler: order, already_seen)) return results targets, alias, _ = self.query.trim_joins(targets, joins, path) - return [(OrderBy(t.get_col(alias), descending=descending), False) for t in targets] + return [(OrderBy(transform_function(t, alias), descending=descending), False) for t in targets] def _setup_joins(self, pieces, opts, alias): """ @@ -677,10 +683,9 @@ class SQLCompiler: match. Executing SQL where this is not true is an error. """ alias = alias or self.query.get_initial_alias() - field, targets, opts, joins, path = self.query.setup_joins( - pieces, opts, alias) + field, targets, opts, joins, path, transform_function = self.query.setup_joins(pieces, opts, alias) alias = joins[-1] - return field, targets, alias, joins, path, opts + return field, targets, alias, joins, path, opts, transform_function def get_from_clause(self): """ @@ -786,7 +791,7 @@ class SQLCompiler: } related_klass_infos.append(klass_info) select_fields = [] - _, _, _, joins, _ = self.query.setup_joins( + _, _, _, joins, _, _ = self.query.setup_joins( [f.name], opts, root_alias) alias = joins[-1] columns = self.get_default_columns(start_alias=alias, opts=f.remote_field.model._meta) @@ -843,7 +848,7 @@ class SQLCompiler: break if name in self.query._filtered_relations: fields_found.add(name) - f, _, join_opts, joins, _ = self.query.setup_joins([name], opts, root_alias) + f, _, join_opts, joins, _, _ = self.query.setup_joins([name], opts, root_alias) model = join_opts.model alias = joins[-1] from_parent = issubclass(model, opts.model) and model is not opts.model -- cgit v1.3