Refs #20939 -- Removed the Query._prepare_as_filter_value() hack.

This commit is contained in:
Simon Charette 2017-04-23 03:01:47 -04:00
parent ec50937bcb
commit c9159a082e
2 changed files with 17 additions and 22 deletions

View File

@ -1099,14 +1099,16 @@ class QuerySet:
for field, objects in other._known_related_objects.items(): for field, objects in other._known_related_objects.items():
self._known_related_objects.setdefault(field, {}).update(objects) 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: if self._fields and len(self._fields) > 1:
# values() queryset can only be used as nested queries # values() queryset can only be used as nested queries
# if they are set up to select only a single field. # if they are set up to select only a single field.
if len(self._fields) > 1: if len(self._fields) > 1:
raise TypeError('Cannot use multi-field values as a filter value.') raise TypeError('Cannot use multi-field values as a filter value.')
queryset = self._clone() query = self.query.resolve_expression(*args, **kwargs)
return queryset.query.as_subquery_filter(queryset._db) query._db = self._db
return query
resolve_expression.queryset_only = True
def _add_hints(self, **hints): def _add_hints(self, **hints):
""" """

View File

@ -976,8 +976,18 @@ class Query:
self.append_annotation_mask([alias]) self.append_annotation_mask([alias])
self.annotations[alias] = annotation self.annotations[alias] = annotation
def _prepare_as_filter_value(self): def resolve_expression(self, query, *args, **kwargs):
return self.clone() 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): def prepare_lookup_value(self, value, lookups, can_reuse, allow_joins=True):
# Default lookup if none given is exact. # 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 a tuple of expressions is the union of
# the used_joins for the individual expressions. # 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)) 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 # For Oracle '' is equivalent to null. The check needs to be done
# at this stage because join promotion can't be done at compiler # 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 # stage. Using DEFAULT_DB_ALIAS isn't nice, but it is the best we
@ -1981,17 +1985,6 @@ class Query:
else: else:
return field.null 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'): def get_order_dir(field, default='ASC'):
""" """