summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorDavid Wobrock <david.wobrock@gmail.com>2022-06-17 09:20:27 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-06-17 11:13:05 +0200
commitd44dc31fcb98935a9e1ec7c5fe60862d2ae4febc (patch)
tree26d4af15b8696d165e9b016ba637a31192fbe6aa /django/db
parentccb243847e300283aca23af5eb3b6b4f2bdcfb28 (diff)
[4.1.x] Fixed #28897 -- Fixed QuerySet.update() on querysets ordered by annotations.
Backport of 3ef37a5245015f69a9b9f884ebc289a35d02c5f6 from main
Diffstat (limited to 'django/db')
-rw-r--r--django/db/backends/mysql/features.py1
-rw-r--r--django/db/models/query.py14
2 files changed, 15 insertions, 0 deletions
diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py
index 9583910b1e..1ac1c59be4 100644
--- a/django/db/backends/mysql/features.py
+++ b/django/db/backends/mysql/features.py
@@ -109,6 +109,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"related fields.": {
"update.tests.AdvancedTests."
"test_update_ordered_by_inline_m2m_annotation",
+ "update.tests.AdvancedTests.test_update_ordered_by_m2m_annotation",
},
}
if "ONLY_FULL_GROUP_BY" in self.connection.sql_mode:
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 67fcb411eb..4e2882e062 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -1159,6 +1159,20 @@ class QuerySet:
self._for_write = True
query = self.query.chain(sql.UpdateQuery)
query.add_update_values(kwargs)
+
+ # Inline annotations in order_by(), if possible.
+ new_order_by = []
+ for col in query.order_by:
+ if annotation := query.annotations.get(col):
+ if getattr(annotation, "contains_aggregate", False):
+ raise exceptions.FieldError(
+ f"Cannot update when ordering by an aggregate: {annotation}"
+ )
+ new_order_by.append(annotation)
+ else:
+ new_order_by.append(col)
+ query.order_by = tuple(new_order_by)
+
# Clear any annotations so that they won't be present in subqueries.
query.annotations = {}
with transaction.mark_for_rollback_on_error(using=self.db):