summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2021-06-05 01:06:17 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-08-30 12:08:04 +0200
commit3219dd3388c437b4bd869b76ddd43c9cdad05090 (patch)
tree53db28fd03110483db1b5f7862e0233d12ee8ebb
parent9e17cc062c62eec1177aaf65ebebba43e074cde2 (diff)
Fixed #24900 -- Allowed migrating backward to squashed migrations.
-rw-r--r--django/db/migrations/executor.py9
-rw-r--r--tests/migrations/test_commands.py13
-rw-r--r--tests/migrations/test_executor.py24
3 files changed, 46 insertions, 0 deletions
diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py
index db9013575e..aa2fe0883b 100644
--- a/django/db/migrations/executor.py
+++ b/django/db/migrations/executor.py
@@ -40,6 +40,15 @@ class MigrationExecutor:
# If the migration is already applied, do backwards mode,
# otherwise do forwards mode.
elif target in applied:
+ # If the target is missing, it's likely a replaced migration.
+ # Reload the graph without replacements.
+ if (
+ self.loader.replace_migrations and
+ target not in self.loader.graph.node_map
+ ):
+ self.loader.replace_migrations = False
+ self.loader.build_graph()
+ return self.migration_plan(targets, clean_start=clean_start)
# Don't migrate backwards all the way to the target node (that
# may roll back dependencies in other apps that don't need to
# be rolled back); instead roll back through target's immediate
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 563b1bd146..d545f125dd 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -980,6 +980,19 @@ class MigrateTests(MigrationTestBase):
# Unmigrate everything.
call_command('migrate', 'migrations', 'zero', verbosity=0)
+ @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'})
+ def test_migrate_backward_to_squashed_migration(self):
+ try:
+ call_command('migrate', 'migrations', '0001_squashed_0002', verbosity=0)
+ self.assertTableExists('migrations_author')
+ self.assertTableExists('migrations_book')
+ call_command('migrate', 'migrations', '0001_initial', verbosity=0)
+ self.assertTableExists('migrations_author')
+ self.assertTableNotExists('migrations_book')
+ finally:
+ # Unmigrate everything.
+ call_command('migrate', 'migrations', 'zero', verbosity=0)
+
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations'})
def test_migrate_inconsistent_history(self):
"""
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index fc80c950fa..f8c321b0f3 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -104,6 +104,29 @@ class ExecutorTests(MigrationTestBase):
self.assertTableNotExists("migrations_author")
self.assertTableNotExists("migrations_book")
+ @override_settings(
+ MIGRATION_MODULES={'migrations': 'migrations.test_migrations_squashed'},
+ )
+ def test_migrate_backward_to_squashed_migration(self):
+ executor = MigrationExecutor(connection)
+ try:
+ self.assertTableNotExists('migrations_author')
+ self.assertTableNotExists('migrations_book')
+ executor.migrate([('migrations', '0001_squashed_0002')])
+ self.assertTableExists('migrations_author')
+ self.assertTableExists('migrations_book')
+ executor.loader.build_graph()
+ # Migrate backward to a squashed migration.
+ executor.migrate([('migrations', '0001_initial')])
+ self.assertTableExists('migrations_author')
+ self.assertTableNotExists('migrations_book')
+ finally:
+ # Unmigrate everything.
+ executor = MigrationExecutor(connection)
+ executor.migrate([('migrations', None)])
+ self.assertTableNotExists('migrations_author')
+ self.assertTableNotExists('migrations_book')
+
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_non_atomic"})
def test_non_atomic_migration(self):
"""
@@ -733,6 +756,7 @@ class FakeLoader:
def __init__(self, graph, applied):
self.graph = graph
self.applied_migrations = applied
+ self.replace_migrations = True
class FakeMigration: