summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2014-08-04 11:58:44 +1000
committerAndrew Godwin <andrew@aeracode.org>2014-08-04 11:59:29 +1000
commitc06e124b5e73bd99c6ec563c64fd50d6a45457d8 (patch)
tree1817236008a0e137713f6e3d9d2f1b3137e14697
parent1b00738f73444693dd94958f3fc53c089f4d96e7 (diff)
Fixed #23091: CreateModel and AddField were clashing with deferred SQL
-rw-r--r--django/db/backends/schema.py4
-rw-r--r--tests/migrations/test_operations.py27
-rw-r--r--tests/schema/tests.py42
3 files changed, 72 insertions, 1 deletions
diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py
index c9052e29d8..b10412751d 100644
--- a/django/db/backends/schema.py
+++ b/django/db/backends/schema.py
@@ -546,6 +546,7 @@ class BaseDatabaseSchemaEditor(object):
}
)
# Drop any FK constraints, we'll remake them later
+ fks_dropped = set()
if old_field.rel:
fk_names = self._constraint_names(model, [old_field.column], foreign_key=True)
if strict and len(fk_names) != 1:
@@ -555,6 +556,7 @@ class BaseDatabaseSchemaEditor(object):
old_field.column,
))
for fk_name in fk_names:
+ fks_dropped.add((old_field.column,))
self.execute(
self.sql_delete_fk % {
"table": self.quote_name(model._meta.db_table),
@@ -737,7 +739,7 @@ class BaseDatabaseSchemaEditor(object):
}
)
# Does it have a foreign key?
- if new_field.rel:
+ if new_field.rel and fks_dropped:
to_table = new_field.rel.to._meta.db_table
to_column = new_field.rel.get_related_field().column
self.execute(
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 78ae508593..9e54f81033 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -1051,6 +1051,33 @@ class OperationTests(OperationTestBase):
operation.database_backwards("test_alorwrtto", editor, new_state, project_state)
self.assertColumnNotExists("test_alorwrtto_rider", "_order")
+ def test_alter_fk(self):
+ """
+ Tests that creating and then altering an FK works correctly
+ and deals with the pending SQL (#23091)
+ """
+ project_state = self.set_up_test_model("test_alfk")
+ # Test adding and then altering the FK in one go
+ create_operation = migrations.CreateModel(
+ name="Rider",
+ fields=[
+ ("id", models.AutoField(primary_key=True)),
+ ("pony", models.ForeignKey(to="Pony")),
+ ],
+ )
+ create_state = project_state.clone()
+ create_operation.state_forwards("test_alfk", create_state)
+ alter_operation = migrations.AlterField(
+ model_name='Rider',
+ name='pony',
+ field=models.ForeignKey(editable=False, to="Pony"),
+ )
+ alter_state = create_state.clone()
+ alter_operation.state_forwards("test_alfk", alter_state)
+ with connection.schema_editor() as editor:
+ create_operation.database_forwards("test_alfk", editor, project_state, create_state)
+ alter_operation.database_forwards("test_alfk", editor, create_state, alter_state)
+
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
def test_run_sql(self):
"""
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index 0bbf4302c9..64726aff4e 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -331,6 +331,48 @@ class SchemaTests(TransactionTestCase):
self.assertEqual(columns['name'][0], "TextField")
self.assertEqual(bool(columns['name'][1][6]), False)
+ @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support")
+ def test_alter_fk(self):
+ """
+ Tests altering of FKs
+ """
+ # Create the table
+ with connection.schema_editor() as editor:
+ editor.create_model(Author)
+ editor.create_model(Book)
+ # Ensure the field is right to begin with
+ columns = self.column_classes(Book)
+ self.assertEqual(columns['author_id'][0], "IntegerField")
+ # Make sure the FK constraint is present
+ constraints = self.get_constraints(Book._meta.db_table)
+ for name, details in constraints.items():
+ if details['columns'] == ["author_id"] and details['foreign_key']:
+ self.assertEqual(details['foreign_key'], ('schema_author', 'id'))
+ break
+ else:
+ self.fail("No FK constraint for author_id found")
+ # Alter the FK
+ new_field = ForeignKey(Author, editable=False)
+ new_field.set_attributes_from_name("author")
+ with connection.schema_editor() as editor:
+ editor.alter_field(
+ Book,
+ Book._meta.get_field_by_name("author")[0],
+ new_field,
+ strict=True,
+ )
+ # Ensure the field is right afterwards
+ columns = self.column_classes(Book)
+ self.assertEqual(columns['author_id'][0], "IntegerField")
+ # Make sure the FK constraint is present
+ constraints = self.get_constraints(Book._meta.db_table)
+ for name, details in constraints.items():
+ if details['columns'] == ["author_id"] and details['foreign_key']:
+ self.assertEqual(details['foreign_key'], ('schema_author', 'id'))
+ break
+ else:
+ self.fail("No FK constraint for author_id found")
+
def test_rename(self):
"""
Tests simple altering of fields