From 065b2a82f6d7539032e15308351fa5eee95c0cb9 Mon Sep 17 00:00:00 2001
From: Tim Graham <timograham@gmail.com>
Date: Thu, 15 Jan 2015 09:56:07 -0500
Subject: [PATCH] [1.7.x] Fixed #24135 -- Made RenameModel rename many-to-many
 tables.

Thanks Simon and Markus for reviews.

Backport of 28db4af80a319485c0da724d692e2f8396aa57e3 from master
---
 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 bb7f11d90d..3d92b68c65 100644
--- a/django/db/migrations/operations/models.py
+++ b/django/db/migrations/operations/models.py
@@ -171,6 +171,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.parent_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, self.old_name = self.old_name, self.new_name
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 435a3f2668..06a22d0f37 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -498,6 +498,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.