From ff3a2834224f527ca574b5cd0d578c8c26d51a6c Mon Sep 17 00:00:00 2001 From: DevilsAutumn Date: Fri, 10 Feb 2023 16:32:31 +0530 Subject: [PATCH] Fixed #34250 -- Fixed renaming model with m2m relation to a model with the same name. --- django/db/migrations/operations/models.py | 20 ++----- tests/migrations/test_operations.py | 69 +++++++++++++++++++++++ 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index 8847441a03c..967a91fdc89 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -407,20 +407,12 @@ class RenameModel(ModelOperation): or not new_field.remote_field.through._meta.auto_created ): continue - # Rename the M2M table that's based on this model's name. - old_m2m_model = old_field.remote_field.through - new_m2m_model = new_field.remote_field.through - schema_editor.alter_db_table( - new_m2m_model, - old_m2m_model._meta.db_table, - new_m2m_model._meta.db_table, - ) - # Rename the column in the M2M table that's based on this - # model's name. - schema_editor.alter_field( - new_m2m_model, - old_m2m_model._meta.get_field(old_model._meta.model_name), - new_m2m_model._meta.get_field(new_model._meta.model_name), + # Rename columns and the M2M table. + schema_editor._alter_many_to_many( + new_model, + old_field, + new_field, + strict=False, ) def database_backwards(self, app_label, schema_editor, from_state, to_state): diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 129360629d7..2f97659046a 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1058,6 +1058,75 @@ class OperationTests(OperationTestBase): Pony._meta.get_field("riders").remote_field.through.objects.count(), 2 ) + def test_rename_model_with_m2m_models_in_different_apps_with_same_name(self): + app_label_1 = "test_rmw_m2m_1" + app_label_2 = "test_rmw_m2m_2" + project_state = self.apply_operations( + app_label_1, + ProjectState(), + operations=[ + migrations.CreateModel( + "Rider", + fields=[ + ("id", models.AutoField(primary_key=True)), + ], + ), + ], + ) + project_state = self.apply_operations( + app_label_2, + project_state, + operations=[ + migrations.CreateModel( + "Rider", + fields=[ + ("id", models.AutoField(primary_key=True)), + ("riders", models.ManyToManyField(f"{app_label_1}.Rider")), + ], + ), + ], + ) + m2m_table = f"{app_label_2}_rider_riders" + self.assertColumnExists(m2m_table, "from_rider_id") + self.assertColumnExists(m2m_table, "to_rider_id") + + Rider_1 = project_state.apps.get_model(app_label_1, "Rider") + Rider_2 = project_state.apps.get_model(app_label_2, "Rider") + rider_2 = Rider_2.objects.create() + rider_2.riders.add(Rider_1.objects.create()) + # Rename model. + project_state_2 = project_state.clone() + project_state = self.apply_operations( + app_label_2, + project_state, + operations=[migrations.RenameModel("Rider", "Pony")], + atomic=connection.features.supports_atomic_references_rename, + ) + + m2m_table = f"{app_label_2}_pony_riders" + self.assertColumnExists(m2m_table, "pony_id") + self.assertColumnExists(m2m_table, "rider_id") + + Rider_1 = project_state.apps.get_model(app_label_1, "Rider") + Rider_2 = project_state.apps.get_model(app_label_2, "Pony") + rider_2 = Rider_2.objects.create() + rider_2.riders.add(Rider_1.objects.create()) + self.assertEqual(Rider_1.objects.count(), 2) + self.assertEqual(Rider_2.objects.count(), 2) + self.assertEqual( + Rider_2._meta.get_field("riders").remote_field.through.objects.count(), 2 + ) + # Reversal. + self.unapply_operations( + app_label_2, + project_state_2, + operations=[migrations.RenameModel("Rider", "Pony")], + atomic=connection.features.supports_atomic_references_rename, + ) + m2m_table = f"{app_label_2}_rider_riders" + self.assertColumnExists(m2m_table, "to_rider_id") + self.assertColumnExists(m2m_table, "from_rider_id") + def test_rename_model_with_db_table_rename_m2m(self): app_label = "test_rmwdbrm2m" project_state = self.apply_operations(