From 71820c9f91a70076526e2f526236fc4172d92fea Mon Sep 17 00:00:00 2001 From: donghao Date: Sat, 9 Sep 2023 22:49:47 +0800 Subject: [PATCH] Fixed #34820 -- Fixed migrations crash when changing a ForeignObject field. --- AUTHORS | 1 + django/db/backends/base/schema.py | 2 ++ tests/migrations/test_operations.py | 46 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/AUTHORS b/AUTHORS index 51a2b1197a..6593f0889f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -391,6 +391,7 @@ answer newbie questions, and generally made Django that much better: Hang Park Hannes Ljungberg Hannes Struß + Hao Dong Harm Geerts Hasan Ramezani Hawkeye diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py index 497008dcd6..493a47548a 100644 --- a/django/db/backends/base/schema.py +++ b/django/db/backends/base/schema.py @@ -1617,6 +1617,8 @@ class BaseDatabaseSchemaEditor: return output def _field_should_be_altered(self, old_field, new_field, ignore=None): + if not old_field.concrete and not new_field.concrete: + return False ignore = ignore or set() _, old_path, old_args, old_kwargs = old_field.deconstruct() _, new_path, new_args, new_kwargs = new_field.deconstruct() diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index d4fc3e855a..01197d5fc8 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -2306,6 +2306,52 @@ class OperationTests(OperationTestBase): operation.database_forwards(app_label, editor, new_state, project_state) self.assertColumnExists(rider_table, "pony_id") + def test_alter_field_foreignobject_noop(self): + app_label = "test_alflfo_noop" + project_state = self.set_up_test_model(app_label) + project_state = self.apply_operations( + app_label, + project_state, + [ + migrations.CreateModel( + "Rider", + fields=[ + ("pony_id", models.IntegerField()), + ( + "pony", + models.ForeignObject( + f"{app_label}.Pony", + models.CASCADE, + from_fields=("pony_id",), + to_fields=("id",), + ), + ), + ], + ), + ], + ) + operation = migrations.AlterField( + "Rider", + "pony", + models.ForeignObject( + f"{app_label}.Pony", + models.CASCADE, + from_fields=("pony_id",), + to_fields=("id",), + null=True, + ), + ) + new_state = project_state.clone() + operation.state_forwards(app_label, new_state) + with ( + CaptureQueriesContext(connection) as ctx, + connection.schema_editor() as editor, + ): + operation.database_forwards(app_label, editor, project_state, new_state) + self.assertIs( + any("ALTER" in query["sql"] for query in ctx.captured_queries), False + ) + @skipUnlessDBFeature("supports_comments") def test_alter_model_table_comment(self): app_label = "test_almotaco"