From 71c8ae543ffec847ec275859bc406202f5029604 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= <motiejus.jakstys@spilgames.com>
Date: Wed, 16 Apr 2014 16:55:34 +0200
Subject: [PATCH] [1.7.x] Fixed #22460 -- Explicity remove constraints when
 dropping a related field.

Backport of 0e45669fa9 from master
---
 django/db/backends/schema.py        | 12 ++++++++++--
 tests/migrations/test_operations.py | 16 ++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py
index d5bb08e12cb..63b0725e22c 100644
--- a/django/db/backends/schema.py
+++ b/django/db/backends/schema.py
@@ -442,8 +442,16 @@ class BaseDatabaseSchemaEditor(object):
         # It might not actually have a column behind it
         if field.db_parameters(connection=self.connection)['type'] is None:
             return
-        # Get the column's definition
-        definition, params = self.column_sql(model, field)
+        # Drop any FK constraints, MySQL requires explicit deletion
+        if field.rel:
+            fk_names = self._constraint_names(model, [field.column], foreign_key=True)
+            for fk_name in fk_names:
+                self.execute(
+                    self.sql_delete_fk % {
+                        "table": self.quote_name(model._meta.db_table),
+                        "name": fk_name,
+                    }
+                )
         # Delete the column
         sql = self.sql_delete_column % {
             "table": self.quote_name(model._meta.db_table),
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index efa16ee7a09..6472fea42cc 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -416,6 +416,22 @@ class OperationTests(MigrationTestBase):
             operation.database_backwards("test_rmfl", editor, new_state, project_state)
         self.assertColumnExists("test_rmfl_pony", "pink")
 
+    def test_remove_fk(self):
+        """
+        Tests the RemoveField operation on a foreign key.
+        """
+        project_state = self.set_up_test_model("test_rfk", related_model=True)
+        self.assertColumnExists("test_rfk_rider", "pony_id")
+        operation = migrations.RemoveField("Rider", "pony")
+        new_state = project_state.clone()
+        operation.state_forwards("test_rfk", new_state)
+        with connection.schema_editor() as editor:
+            operation.database_forwards("test_rfk", editor, project_state, new_state)
+        self.assertColumnNotExists("test_rfk_rider", "pony_id")
+        with connection.schema_editor() as editor:
+            operation.database_backwards("test_rfk", editor, new_state, project_state)
+        self.assertColumnExists("test_rfk_rider", "pony_id")
+
     def test_alter_model_table(self):
         """
         Tests the AlterModelTable operation.