diff options
Diffstat (limited to 'django/db/models/fields')
| -rw-r--r-- | django/db/models/fields/tuple_lookups.py | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/django/db/models/fields/tuple_lookups.py b/django/db/models/fields/tuple_lookups.py index 51432a666b..2f195f25b9 100644 --- a/django/db/models/fields/tuple_lookups.py +++ b/django/db/models/fields/tuple_lookups.py @@ -2,7 +2,7 @@ import itertools from django.core.exceptions import EmptyResultSet from django.db.models import Field -from django.db.models.expressions import ColPairs, Func, Value +from django.db.models.expressions import ColPairs, Func, ResolvedOuterRef, Value from django.db.models.lookups import ( Exact, GreaterThan, @@ -32,8 +32,11 @@ class TupleLookupMixin: allows_composite_expressions = True def get_prep_lookup(self): - self.check_rhs_is_tuple_or_list() - self.check_rhs_length_equals_lhs_length() + if self.rhs_is_direct_value(): + self.check_rhs_is_tuple_or_list() + self.check_rhs_length_equals_lhs_length() + else: + self.check_rhs_is_outer_ref() return self.rhs def check_rhs_is_tuple_or_list(self): @@ -51,6 +54,15 @@ class TupleLookupMixin: f"{self.lookup_name!r} lookup of {lhs_str} must have {len_lhs} elements" ) + def check_rhs_is_outer_ref(self): + if not isinstance(self.rhs, ResolvedOuterRef): + lhs_str = self.get_lhs_str() + rhs_cls = self.rhs.__class__.__name__ + raise ValueError( + f"{self.lookup_name!r} subquery lookup of {lhs_str} " + f"only supports OuterRef objects (received {rhs_cls!r})" + ) + def get_lhs_str(self): if isinstance(self.lhs, ColPairs): return repr(self.lhs.field.name) @@ -70,11 +82,19 @@ class TupleLookupMixin: return sql, params def process_rhs(self, compiler, connection): - values = [ - Value(val, output_field=col.output_field) - for col, val in zip(self.lhs, self.rhs) - ] - return Tuple(*values).as_sql(compiler, connection) + if self.rhs_is_direct_value(): + args = [ + Value(val, output_field=col.output_field) + for col, val in zip(self.lhs, self.rhs) + ] + return Tuple(*args).as_sql(compiler, connection) + else: + sql, params = compiler.compile(self.rhs) + if not isinstance(self.rhs, ColPairs): + raise ValueError( + "Composite field lookups only work with composite expressions." + ) + return "(%s)" % sql, params class TupleExact(TupleLookupMixin, Exact): |
