Loading django/db/migrations/operations/special.py +2 −2 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ class SeparateDatabaseAndState(Operation): for database_operation in self.database_operations: to_state = from_state.clone() database_operation.state_forwards(app_label, to_state) database_operation.database_forwards(self, app_label, schema_editor, from_state, to_state) database_operation.database_forwards(app_label, schema_editor, from_state, to_state) from_state = to_state def database_backwards(self, app_label, schema_editor, from_state, to_state): Loading @@ -36,7 +36,7 @@ class SeparateDatabaseAndState(Operation): dbop.state_forwards(app_label, to_state) from_state = base_state.clone() database_operation.state_forwards(app_label, from_state) database_operation.database_backwards(self, app_label, schema_editor, from_state, to_state) database_operation.database_backwards(app_label, schema_editor, from_state, to_state) def describe(self): return "Custom state/database change combination" Loading tests/migrations/test_operations.py +33 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,39 @@ class OperationTests(OperationTestBase): non_atomic_migration.apply(project_state, editor) self.assertEqual(project_state.render().get_model("test_runpythonatomic", "Pony").objects.count(), 1) @unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse") def test_separate_database_and_state(self): """ Tests the SeparateDatabaseAndState operation. """ project_state = self.set_up_test_model("test_separatedatabaseandstate") # Create the operation database_operation = migrations.RunSQL( "CREATE TABLE i_love_ponies (id int, special_thing int);", "DROP TABLE i_love_ponies;" ) state_operation = migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))]) operation = migrations.SeparateDatabaseAndState( state_operations=[state_operation], database_operations=[database_operation] ) self.assertEqual(operation.describe(), "Custom state/database change combination") # Test the state alteration new_state = project_state.clone() operation.state_forwards("test_separatedatabaseandstate", new_state) self.assertEqual(len(new_state.models["test_separatedatabaseandstate", "somethingelse"].fields), 1) # Make sure there's no table self.assertTableNotExists("i_love_ponies") # Test the database alteration with connection.schema_editor() as editor: operation.database_forwards("test_separatedatabaseandstate", editor, project_state, new_state) self.assertTableExists("i_love_ponies") # And test reversal self.assertTrue(operation.reversible) with connection.schema_editor() as editor: operation.database_backwards("test_separatedatabaseandstate", editor, new_state, project_state) self.assertTableNotExists("i_love_ponies") class MigrateNothingRouter(object): """ Loading Loading
django/db/migrations/operations/special.py +2 −2 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ class SeparateDatabaseAndState(Operation): for database_operation in self.database_operations: to_state = from_state.clone() database_operation.state_forwards(app_label, to_state) database_operation.database_forwards(self, app_label, schema_editor, from_state, to_state) database_operation.database_forwards(app_label, schema_editor, from_state, to_state) from_state = to_state def database_backwards(self, app_label, schema_editor, from_state, to_state): Loading @@ -36,7 +36,7 @@ class SeparateDatabaseAndState(Operation): dbop.state_forwards(app_label, to_state) from_state = base_state.clone() database_operation.state_forwards(app_label, from_state) database_operation.database_backwards(self, app_label, schema_editor, from_state, to_state) database_operation.database_backwards(app_label, schema_editor, from_state, to_state) def describe(self): return "Custom state/database change combination" Loading
tests/migrations/test_operations.py +33 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,39 @@ class OperationTests(OperationTestBase): non_atomic_migration.apply(project_state, editor) self.assertEqual(project_state.render().get_model("test_runpythonatomic", "Pony").objects.count(), 1) @unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse") def test_separate_database_and_state(self): """ Tests the SeparateDatabaseAndState operation. """ project_state = self.set_up_test_model("test_separatedatabaseandstate") # Create the operation database_operation = migrations.RunSQL( "CREATE TABLE i_love_ponies (id int, special_thing int);", "DROP TABLE i_love_ponies;" ) state_operation = migrations.CreateModel("SomethingElse", [("id", models.AutoField(primary_key=True))]) operation = migrations.SeparateDatabaseAndState( state_operations=[state_operation], database_operations=[database_operation] ) self.assertEqual(operation.describe(), "Custom state/database change combination") # Test the state alteration new_state = project_state.clone() operation.state_forwards("test_separatedatabaseandstate", new_state) self.assertEqual(len(new_state.models["test_separatedatabaseandstate", "somethingelse"].fields), 1) # Make sure there's no table self.assertTableNotExists("i_love_ponies") # Test the database alteration with connection.schema_editor() as editor: operation.database_forwards("test_separatedatabaseandstate", editor, project_state, new_state) self.assertTableExists("i_love_ponies") # And test reversal self.assertTrue(operation.reversible) with connection.schema_editor() as editor: operation.database_backwards("test_separatedatabaseandstate", editor, new_state, project_state) self.assertTableNotExists("i_love_ponies") class MigrateNothingRouter(object): """ Loading