Fixed #25896 -- Fixed state bug in SeparateDatabaseAndState.database_backwards().

This commit is contained in:
Amos Onn 2015-12-08 19:03:31 +02:00 committed by Tim Graham
parent 890938e756
commit 542b7f6c50
4 changed files with 83 additions and 1 deletions

View File

@ -50,7 +50,7 @@ class SeparateDatabaseAndState(Operation):
to_state = base_state.clone() to_state = base_state.clone()
for dbop in self.database_operations[:-(pos + 1)]: for dbop in self.database_operations[:-(pos + 1)]:
dbop.state_forwards(app_label, to_state) 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.state_forwards(app_label, from_state)
database_operation.database_backwards(app_label, schema_editor, from_state, to_state) database_operation.database_backwards(app_label, schema_editor, from_state, to_state)

View File

@ -27,3 +27,6 @@ Bugfixes
* Restored the ability to use custom formats from ``formats.py`` with * Restored the ability to use custom formats from ``formats.py`` with
``django.utils.formats.get_format()`` and the ``date`` template filter ``django.utils.formats.get_format()`` and the ``date`` template filter
(:ticket:`25812`). (:ticket:`25812`).
* Fixed a state bug when migrating a ``SeparateDatabaseAndState`` operation
backwards (:ticket:`25896`).

View File

@ -16,3 +16,6 @@ Bugfixes
(:ticket:`25548`). (:ticket:`25548`).
* Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`). * Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`).
* Fixed a state bug when migrating a ``SeparateDatabaseAndState`` operation
backwards (:ticket:`25896`).

View File

@ -1850,6 +1850,82 @@ class OperationTests(OperationTestBase):
self.assertEqual(definition[1], []) self.assertEqual(definition[1], [])
self.assertEqual(sorted(definition[2]), ["database_operations", "state_operations"]) 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): class SwappableOperationTests(OperationTestBase):
""" """