From 28db4af80a319485c0da724d692e2f8396aa57e3 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Thu, 15 Jan 2015 09:56:07 -0500 Subject: [PATCH] Fixed #24135 -- Made RenameModel rename many-to-many tables. Thanks Simon and Markus for reviews. --- django/db/migrations/operations/models.py | 21 ++++++++++++++++++ docs/releases/1.7.4.txt | 3 +++ tests/migrations/test_operations.py | 26 +++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index 773c70526f..cdc3c06e50 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -216,6 +216,27 @@ class RenameModel(Operation): related_object.field, to_field, ) + # Rename M2M fields whose name is based on this model's name. + fields = zip(old_model._meta.local_many_to_many, new_model._meta.local_many_to_many) + for (old_field, new_field) in fields: + # Skip self-referential fields as these are renamed above. + if new_field.model == new_field.related_model or not new_field.rel.through._meta.auto_created: + continue + # Rename the M2M table that's based on this model's name. + old_m2m_model = old_field.rel.through + new_m2m_model = new_field.rel.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), + ) def database_backwards(self, app_label, schema_editor, from_state, to_state): self.new_name_lower, self.old_name_lower = self.old_name_lower, self.new_name_lower diff --git a/docs/releases/1.7.4.txt b/docs/releases/1.7.4.txt index 486baa6e07..8fbac815bf 100644 --- a/docs/releases/1.7.4.txt +++ b/docs/releases/1.7.4.txt @@ -11,3 +11,6 @@ Bugfixes * Fixed a migration crash when unapplying ``contrib.contenttypes``’s or ``contrib.auth``’s first migration (:ticket:`24075`). + +* Made the migration's ``RenameModel`` operation rename ``ManyToManyField`` + tables (:ticket:`24135`). diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 12fd807bae..d8a042d4ba 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -553,6 +553,32 @@ class OperationTests(OperationTestBase): pony = Pony.objects.create() pony.ponies.add(pony) + def test_rename_model_with_m2m(self): + app_label = "test_rename_model_with_m2m" + project_state = self.apply_operations(app_label, ProjectState(), operations=[ + migrations.CreateModel("Rider", fields=[]), + migrations.CreateModel("Pony", fields=[ + ("riders", models.ManyToManyField("Rider")), + ]), + ]) + Pony = project_state.apps.get_model(app_label, "Pony") + Rider = project_state.apps.get_model(app_label, "Rider") + pony = Pony.objects.create() + rider = Rider.objects.create() + pony.riders.add(rider) + + project_state = self.apply_operations(app_label, project_state, operations=[ + migrations.RenameModel("Pony", "Pony2"), + ]) + Pony = project_state.apps.get_model(app_label, "Pony2") + Rider = project_state.apps.get_model(app_label, "Rider") + pony = Pony.objects.create() + rider = Rider.objects.create() + pony.riders.add(rider) + self.assertEqual(Pony.objects.count(), 2) + self.assertEqual(Rider.objects.count(), 2) + self.assertEqual(Pony._meta.get_field('riders').rel.through.objects.count(), 2) + def test_add_field(self): """ Tests the AddField operation.