diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 36eee4b2a7..6b2ea0e017 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -9,7 +9,7 @@ from django.db import DatabaseError, NotSupportedError from django.db.models.constants import LOOKUP_SEP from django.db.models.expressions import F, OrderBy, RawSQL, Ref, Value from django.db.models.functions import Cast, Random -from django.db.models.query_utils import Q, select_related_descend +from django.db.models.query_utils import select_related_descend from django.db.models.sql.constants import ( CURSOR, GET_ITERATOR_CHUNK_SIZE, MULTI, NO_RESULTS, ORDER_DIR, SINGLE, ) @@ -1509,7 +1509,7 @@ class SQLDeleteCompiler(SQLCompiler): # to the target table on MySQL. sql, params = innerq.get_compiler(connection=self.connection).as_sql() innerq = RawSQL('SELECT * FROM (%s) subquery' % sql, params) - outerq.add_q(Q(pk__in=innerq)) + outerq.add_filter('pk__in', innerq) return self._as_sql(outerq) @@ -1633,11 +1633,11 @@ class SQLUpdateCompiler(SQLCompiler): idents = [] for rows in query.get_compiler(self.using).execute_sql(MULTI): idents.extend(r[0] for r in rows) - self.query.add_filter(('pk__in', idents)) + self.query.add_filter('pk__in', idents) self.query.related_ids = idents else: # The fast path. Filters and updates in one query. - self.query.add_filter(('pk__in', query)) + self.query.add_filter('pk__in', query) self.query.reset_refcounts(refcounts_before) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 8ecac4a3b7..181d4419fa 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1357,8 +1357,8 @@ class Query(BaseExpression): clause.add(lookup_class(value, False), AND) return clause, used_joins if not require_outer else () - def add_filter(self, filter_clause): - self.add_q(Q(**{filter_clause[0]: filter_clause[1]})) + def add_filter(self, filter_lhs, filter_rhs): + self.add_q(Q((filter_lhs, filter_rhs))) def add_q(self, q_object): """ @@ -1762,15 +1762,15 @@ class Query(BaseExpression): LIMIT 1 ) """ - filter_lhs, filter_rhs = filter_expr - if isinstance(filter_rhs, OuterRef): - filter_expr = (filter_lhs, OuterRef(filter_rhs)) - elif isinstance(filter_rhs, F): - filter_expr = (filter_lhs, OuterRef(filter_rhs.name)) # Generate the inner query. query = Query(self.model) query._filtered_relations = self._filtered_relations - query.add_filter(filter_expr) + filter_lhs, filter_rhs = filter_expr + if isinstance(filter_rhs, OuterRef): + filter_rhs = OuterRef(filter_rhs) + elif isinstance(filter_rhs, F): + filter_rhs = OuterRef(filter_rhs.name) + query.add_filter(filter_lhs, filter_rhs) query.clear_ordering(force=True) # Try to have as simple as possible subquery -> trim leading joins from # the subquery. diff --git a/django/db/models/sql/subqueries.py b/django/db/models/sql/subqueries.py index 904f1d096b..b1e5d2f5b7 100644 --- a/django/db/models/sql/subqueries.py +++ b/django/db/models/sql/subqueries.py @@ -3,7 +3,6 @@ Query subclasses which provide extra functionality beyond simple data retrieval. """ from django.core.exceptions import FieldError -from django.db.models.query_utils import Q from django.db.models.sql.constants import ( CURSOR, GET_ITERATOR_CHUNK_SIZE, NO_RESULTS, ) @@ -38,8 +37,10 @@ class DeleteQuery(Query): field = self.get_meta().pk for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): self.clear_where() - self.add_q(Q( - **{field.attname + '__in': pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]})) + self.add_filter( + f'{field.attname}__in', + pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE], + ) num_deleted += self.do_query(self.get_meta().db_table, self.where, using=using) return num_deleted @@ -71,7 +72,7 @@ class UpdateQuery(Query): self.add_update_values(values) for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): self.clear_where() - self.add_q(Q(pk__in=pk_list[offset: offset + GET_ITERATOR_CHUNK_SIZE])) + self.add_filter('pk__in', pk_list[offset: offset + GET_ITERATOR_CHUNK_SIZE]) self.get_compiler(using).execute_sql(NO_RESULTS) def add_update_values(self, values): @@ -129,7 +130,7 @@ class UpdateQuery(Query): query = UpdateQuery(model) query.values = values if self.related_ids is not None: - query.add_filter(('pk__in', self.related_ids)) + query.add_filter('pk__in', self.related_ids) result.append(query) return result diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index 7275e1712d..54fe611595 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -516,6 +516,10 @@ Miscellaneous ``ForeignObject`` and ``ForeignObjectRel`` are removed. If needed, initialize ``django.db.models.sql.where.WhereNode`` instead. +* The ``filter_clause`` argument of the undocumented ``Query.add_filter()`` + method is replaced by two positional arguments ``filter_lhs`` and + ``filter_rhs``. + .. _deprecated-features-4.0: Features deprecated in 4.0