summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2017-04-23 03:01:47 -0400
committerSimon Charette <charette.s@gmail.com>2017-04-25 23:43:33 -0400
commitc9159a082ebe41a1f735f8d01720e746fb43c41e (patch)
treeeabfeb4b8160443229aa5f9cdedf46493ba77f5a
parentec50937bcbe160e658ef881021402e156beb0eaf (diff)
Refs #20939 -- Removed the Query._prepare_as_filter_value() hack.
-rw-r--r--django/db/models/query.py8
-rw-r--r--django/db/models/sql/query.py31
2 files changed, 17 insertions, 22 deletions
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'):
"""