mirror of https://github.com/django/django.git
Fixed #22095 -- Enabled backward migrations for RunPython operations
Added reversible property to RunPython so that migrations will not refuse to reverse migrations including RunPython operations, so long as reverse_code is set in the RunPython constructor. Included tests to check the reversible property on RunPython and the similar RunSQL.
This commit is contained in:
parent
b887408486
commit
202bf69c2f
|
@ -103,7 +103,6 @@ class RunPython(Operation):
|
|||
"""
|
||||
|
||||
reduces_to_sql = False
|
||||
reversible = False
|
||||
|
||||
def __init__(self, code, reverse_code=None):
|
||||
# Forwards code
|
||||
|
@ -118,6 +117,10 @@ class RunPython(Operation):
|
|||
raise ValueError("RunPython must be supplied with callable arguments")
|
||||
self.reverse_code = reverse_code
|
||||
|
||||
@property
|
||||
def reversible(self):
|
||||
return self.reverse_code is not None
|
||||
|
||||
def state_forwards(self, app_label, state):
|
||||
# RunPython objects have no state effect. To add some, combine this
|
||||
# with SeparateDatabaseAndState.
|
||||
|
|
|
@ -468,6 +468,7 @@ class OperationTests(MigrationTestBase):
|
|||
operation.database_forwards("test_runsql", 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_runsql", editor, new_state, project_state)
|
||||
self.assertTableNotExists("i_love_ponies")
|
||||
|
@ -484,7 +485,11 @@ class OperationTests(MigrationTestBase):
|
|||
Pony = models.get_model("test_runpython", "Pony")
|
||||
Pony.objects.create(pink=1, weight=3.55)
|
||||
Pony.objects.create(weight=5)
|
||||
operation = migrations.RunPython(inner_method)
|
||||
def inner_method_reverse(models, schema_editor):
|
||||
Pony = models.get_model("test_runpython", "Pony")
|
||||
Pony.objects.filter(pink=1, weight=3.55).delete()
|
||||
Pony.objects.filter(weight=5).delete()
|
||||
operation = migrations.RunPython(inner_method, reverse_code=inner_method_reverse)
|
||||
# Test the state alteration does nothing
|
||||
new_state = project_state.clone()
|
||||
operation.state_forwards("test_runpython", new_state)
|
||||
|
@ -494,13 +499,24 @@ class OperationTests(MigrationTestBase):
|
|||
with connection.schema_editor() as editor:
|
||||
operation.database_forwards("test_runpython", editor, project_state, new_state)
|
||||
self.assertEqual(project_state.render().get_model("test_runpython", "Pony").objects.count(), 2)
|
||||
# And test reversal fails
|
||||
with self.assertRaises(NotImplementedError):
|
||||
operation.database_backwards("test_runpython", None, new_state, project_state)
|
||||
# Now test reversal
|
||||
self.assertTrue(operation.reversible)
|
||||
with connection.schema_editor() as editor:
|
||||
operation.database_backwards("test_runpython", editor, project_state, new_state)
|
||||
self.assertEqual(project_state.render().get_model("test_runpython", "Pony").objects.count(), 0)
|
||||
# Now test we can't use a string
|
||||
with self.assertRaises(ValueError):
|
||||
operation = migrations.RunPython("print 'ahahaha'")
|
||||
|
||||
# Also test reversal fails, with an operation identical to above but without reverse_code set
|
||||
no_reverse_operation = migrations.RunPython(inner_method)
|
||||
self.assertFalse(no_reverse_operation.reversible)
|
||||
with connection.schema_editor() as editor:
|
||||
no_reverse_operation.database_forwards("test_runpython", editor, project_state, new_state)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
no_reverse_operation.database_backwards("test_runpython", editor, new_state, project_state)
|
||||
|
||||
|
||||
|
||||
class MigrateNothingRouter(object):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue