mirror of https://github.com/django/django.git
Fixed #25896 -- Fixed state bug in SeparateDatabaseAndState.database_backwards().
This commit is contained in:
parent
890938e756
commit
542b7f6c50
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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`).
|
||||||
|
|
|
@ -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`).
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue