mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.9.x] Fixed #25896 -- Fixed state bug in SeparateDatabaseAndState.database_backwards().
Backport of 542b7f6c50 from master
			
			
This commit is contained in:
		| @@ -50,7 +50,7 @@ class SeparateDatabaseAndState(Operation): | ||||
|             to_state = base_state.clone() | ||||
|             for dbop in self.database_operations[:-(pos + 1)]: | ||||
|                 dbop.state_forwards(app_label, to_state) | ||||
|             from_state = base_state.clone() | ||||
|             from_state = to_state.clone() | ||||
|             database_operation.state_forwards(app_label, from_state) | ||||
|             database_operation.database_backwards(app_label, schema_editor, from_state, to_state) | ||||
|  | ||||
|   | ||||
| @@ -27,3 +27,6 @@ Bugfixes | ||||
| * Restored the ability to use custom formats from ``formats.py`` with | ||||
|   ``django.utils.formats.get_format()`` and the ``date`` template filter | ||||
|   (:ticket:`25812`). | ||||
|  | ||||
| * Fixed a state bug when migrating a ``SeparateDatabaseAndState`` operation | ||||
|   backwards (:ticket:`25896`). | ||||
|   | ||||
| @@ -16,3 +16,6 @@ Bugfixes | ||||
|   (:ticket:`25548`). | ||||
|  | ||||
| * Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`). | ||||
|  | ||||
| * Fixed a state bug when migrating a ``SeparateDatabaseAndState`` operation | ||||
|   backwards (:ticket:`25896`). | ||||
|   | ||||
| @@ -1850,6 +1850,82 @@ class OperationTests(OperationTestBase): | ||||
|         self.assertEqual(definition[1], []) | ||||
|         self.assertEqual(sorted(definition[2]), ["database_operations", "state_operations"]) | ||||
|  | ||||
|     def test_separate_database_and_state2(self): | ||||
|         """ | ||||
|         A complex SeparateDatabaseAndState operation: Multiple operations both | ||||
|         for state and database. Verify the state dependencies within each list | ||||
|         and that state ops don't affect the database. | ||||
|         """ | ||||
|         app_label = "test_separatedatabaseandstate2" | ||||
|         project_state = self.set_up_test_model(app_label) | ||||
|         # Create the operation | ||||
|         database_operations = [ | ||||
|             migrations.CreateModel( | ||||
|                 "ILovePonies", | ||||
|                 [("id", models.AutoField(primary_key=True))], | ||||
|                 options={"db_table": "iloveponies"}, | ||||
|             ), | ||||
|             migrations.CreateModel( | ||||
|                 "ILoveMorePonies", | ||||
|                 [("id", models.AutoField(primary_key=True))], | ||||
|                 options={"db_table": "ilovemoreponies"}, | ||||
|             ), | ||||
|             migrations.DeleteModel("ILoveMorePonies"), | ||||
|             migrations.CreateModel( | ||||
|                 "ILoveEvenMorePonies", | ||||
|                 [("id", models.AutoField(primary_key=True))], | ||||
|                 options={"db_table": "iloveevenmoreponies"}, | ||||
|             ), | ||||
|         ] | ||||
|         state_operations = [ | ||||
|             migrations.CreateModel( | ||||
|                 "SomethingElse", | ||||
|                 [("id", models.AutoField(primary_key=True))], | ||||
|                 options={"db_table": "somethingelse"}, | ||||
|             ), | ||||
|             migrations.DeleteModel("SomethingElse"), | ||||
|             migrations.CreateModel( | ||||
|                 "SomethingCompletelyDifferent", | ||||
|                 [("id", models.AutoField(primary_key=True))], | ||||
|                 options={"db_table": "somethingcompletelydifferent"}, | ||||
|             ), | ||||
|         ] | ||||
|         operation = migrations.SeparateDatabaseAndState( | ||||
|             state_operations=state_operations, | ||||
|             database_operations=database_operations, | ||||
|         ) | ||||
|         # Test the state alteration | ||||
|         new_state = project_state.clone() | ||||
|         operation.state_forwards(app_label, new_state) | ||||
|  | ||||
|         def assertModelsAndTables(after_db): | ||||
|             # Check that tables and models exist, or don't, as they should: | ||||
|             self.assertNotIn((app_label, "somethingelse"), new_state.models) | ||||
|             self.assertEqual(len(new_state.models[app_label, "somethingcompletelydifferent"].fields), 1) | ||||
|             self.assertNotIn((app_label, "iloveponiesonies"), new_state.models) | ||||
|             self.assertNotIn((app_label, "ilovemoreponies"), new_state.models) | ||||
|             self.assertNotIn((app_label, "iloveevenmoreponies"), new_state.models) | ||||
|             self.assertTableNotExists("somethingelse") | ||||
|             self.assertTableNotExists("somethingcompletelydifferent") | ||||
|             self.assertTableNotExists("ilovemoreponies") | ||||
|             if after_db: | ||||
|                 self.assertTableExists("iloveponies") | ||||
|                 self.assertTableExists("iloveevenmoreponies") | ||||
|             else: | ||||
|                 self.assertTableNotExists("iloveponies") | ||||
|                 self.assertTableNotExists("iloveevenmoreponies") | ||||
|  | ||||
|         assertModelsAndTables(after_db=False) | ||||
|         # Test the database alteration | ||||
|         with connection.schema_editor() as editor: | ||||
|             operation.database_forwards(app_label, editor, project_state, new_state) | ||||
|         assertModelsAndTables(after_db=True) | ||||
|         # And test reversal | ||||
|         self.assertTrue(operation.reversible) | ||||
|         with connection.schema_editor() as editor: | ||||
|             operation.database_backwards(app_label, editor, new_state, project_state) | ||||
|         assertModelsAndTables(after_db=False) | ||||
|  | ||||
|  | ||||
| class SwappableOperationTests(OperationTestBase): | ||||
|     """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user