From 7b4a994599b75a07cb07d1e0cc26b3bbf25ab7a6 Mon Sep 17 00:00:00 2001
From: Markus Holtermann <info@markusholtermann.eu>
Date: Mon, 17 Nov 2014 19:04:38 +0100
Subject: [PATCH] Fixed #23859 -- Fixed a migration crash when a field is
 renamed that is part of an index_together

---
 django/db/migrations/operations/fields.py | 13 +++++++------
 docs/releases/1.7.2.txt                   |  3 +++
 tests/migrations/test_operations.py       |  8 ++++++--
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/django/db/migrations/operations/fields.py b/django/db/migrations/operations/fields.py
index 435d4a0936..afa3fde818 100644
--- a/django/db/migrations/operations/fields.py
+++ b/django/db/migrations/operations/fields.py
@@ -177,13 +177,14 @@ class RenameField(Operation):
             (self.new_name if n == self.old_name else n, f)
             for n, f in state.models[app_label, self.model_name.lower()].fields
         ]
-        # Fix unique_together to refer to the new field
+        # Fix index/unique_together to refer to the new field
         options = state.models[app_label, self.model_name.lower()].options
-        if "unique_together" in options:
-            options['unique_together'] = [
-                [self.new_name if n == self.old_name else n for n in unique]
-                for unique in options['unique_together']
-            ]
+        for option in ('index_together', 'unique_together'):
+            if option in options:
+                options[option] = [
+                    [self.new_name if n == self.old_name else n for n in together]
+                    for together in options[option]
+                ]
 
     def database_forwards(self, app_label, schema_editor, from_state, to_state):
         to_model = to_state.render().get_model(app_label, self.model_name)
diff --git a/docs/releases/1.7.2.txt b/docs/releases/1.7.2.txt
index 976210367d..8420b5b303 100644
--- a/docs/releases/1.7.2.txt
+++ b/docs/releases/1.7.2.txt
@@ -59,3 +59,6 @@ Bugfixes
 
 * Fixed a custom field type validation error with MySQL backend when
   ``db_type`` returned ``None`` (:ticket:`23761`).
+
+* Fixed a migration crash when a field is renamed that is part of an
+  ``index_together`` (:ticket:`23859`).
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 6e7e8d2059..09dc25fd26 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -49,7 +49,7 @@ class OperationTestBase(MigrationTestBase):
 
     def set_up_test_model(self, app_label, second_model=False, third_model=False,
             related_model=False, mti_model=False, proxy_model=False,
-            unique_together=False, options=False, db_table=None):
+            unique_together=False, options=False, db_table=None, index_together=False):
         """
         Creates a test model state and database table.
         """
@@ -81,6 +81,7 @@ class OperationTestBase(MigrationTestBase):
         # Make the "current" state
         model_options = {
             "swappable": "TEST_SWAP_MODEL",
+            "index_together": [["pink", "weight"]] if index_together else [],
             "unique_together": [["pink", "weight"]] if unique_together else [],
         }
         if options:
@@ -984,7 +985,7 @@ class OperationTests(OperationTestBase):
         """
         Tests the RenameField operation.
         """
-        project_state = self.set_up_test_model("test_rnfl", unique_together=True)
+        project_state = self.set_up_test_model("test_rnfl", unique_together=True, index_together=True)
         # Test the state alteration
         operation = migrations.RenameField("Pony", "pink", "blue")
         self.assertEqual(operation.describe(), "Rename field pink on Pony to blue")
@@ -995,6 +996,9 @@ class OperationTests(OperationTestBase):
         # Make sure the unique_together has the renamed column too
         self.assertIn("blue", new_state.models["test_rnfl", "pony"].options['unique_together'][0])
         self.assertNotIn("pink", new_state.models["test_rnfl", "pony"].options['unique_together'][0])
+        # Make sure the index_together has the renamed column too
+        self.assertIn("blue", new_state.models["test_rnfl", "pony"].options['index_together'][0])
+        self.assertNotIn("pink", new_state.models["test_rnfl", "pony"].options['index_together'][0])
         # Test the database alteration
         self.assertColumnExists("test_rnfl_pony", "pink")
         self.assertColumnNotExists("test_rnfl_pony", "blue")