diff --git a/django/db/models/query.py b/django/db/models/query.py index f266e2bf22..7302a1dfee 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1099,14 +1099,16 @@ class QuerySet: for field, objects in other._known_related_objects.items(): self._known_related_objects.setdefault(field, {}).update(objects) - def _prepare_as_filter_value(self): + def resolve_expression(self, *args, **kwargs): if self._fields and len(self._fields) > 1: # values() queryset can only be used as nested queries # if they are set up to select only a single field. if len(self._fields) > 1: raise TypeError('Cannot use multi-field values as a filter value.') - queryset = self._clone() - return queryset.query.as_subquery_filter(queryset._db) + query = self.query.resolve_expression(*args, **kwargs) + query._db = self._db + return query + resolve_expression.queryset_only = True def _add_hints(self, **hints): """ diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 8c3ed06040..5c3eca0032 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -976,8 +976,18 @@ class Query: self.append_annotation_mask([alias]) self.annotations[alias] = annotation - def _prepare_as_filter_value(self): - return self.clone() + def resolve_expression(self, query, *args, **kwargs): + clone = self.clone() + # Subqueries need to use a different set of aliases than the outer query. + clone.bump_prefix(query) + clone.subquery = True + # It's safe to drop ordering if the queryset isn't using slicing, + # distinct(*fields) or select_for_update(). + if (self.low_mark == 0 and self.high_mark is None and + not self.distinct_fields and + not self.select_for_update): + clone.clear_ordering(True) + return clone def prepare_lookup_value(self, value, lookups, can_reuse, allow_joins=True): # Default lookup if none given is exact. @@ -1008,12 +1018,6 @@ class Query: # The used_joins for a tuple of expressions is the union of # the used_joins for the individual expressions. used_joins |= set(k for k, v in self.alias_refcount.items() if v > pre_joins.get(k, 0)) - # Subqueries need to use a different set of aliases than the - # outer query. Call bump_prefix to change aliases of the inner - # query (the value). - if hasattr(value, '_prepare_as_filter_value'): - value = value._prepare_as_filter_value() - value.bump_prefix(self) # For Oracle '' is equivalent to null. The check needs to be done # at this stage because join promotion can't be done at compiler # stage. Using DEFAULT_DB_ALIAS isn't nice, but it is the best we @@ -1981,17 +1985,6 @@ class Query: else: return field.null - def as_subquery_filter(self, db): - self._db = db - self.subquery = True - # It's safe to drop ordering if the queryset isn't using slicing, - # distinct(*fields) or select_for_update(). - if (self.low_mark == 0 and self.high_mark is None and - not self.distinct_fields and - not self.select_for_update): - self.clear_ordering(True) - return self - def get_order_dir(field, default='ASC'): """