summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Yanchev <georgi.yanchev@gmail.com>2025-01-20 09:05:28 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-22 10:56:30 +0100
commit322785b08cf21f2b7a627caf459e73e6170dd602 (patch)
tree19be201d6a922d265ca305c1d678c7f8135e1fc4
parent00c690efbc0b10f67924687f24a7b30397bf47d9 (diff)
Refs #24529 -- Added replace_migration hook to MigrationLoader.
-rw-r--r--django/db/migrations/loader.py45
1 files changed, 24 insertions, 21 deletions
diff --git a/django/db/migrations/loader.py b/django/db/migrations/loader.py
index 50445f3101..3f5599bdf5 100644
--- a/django/db/migrations/loader.py
+++ b/django/db/migrations/loader.py
@@ -219,6 +219,28 @@ class MigrationLoader:
if child is not None:
self.graph.add_dependency(migration, child, key, skip_validation=True)
+ def replace_migration(self, migration_key):
+ migration = self.replacements[migration_key]
+ # Get applied status of each found replacement target.
+ applied_statuses = [
+ (target in self.applied_migrations) for target in migration.replaces
+ ]
+ # The replacing migration is only marked as applied if all of its
+ # replacement targets are applied.
+ if all(applied_statuses):
+ self.applied_migrations[migration_key] = migration
+ else:
+ self.applied_migrations.pop(migration_key, None)
+ # A replacing migration can be used if either all or none of its
+ # replacement targets have been applied.
+ if all(applied_statuses) or (not any(applied_statuses)):
+ self.graph.remove_replaced_nodes(migration_key, migration.replaces)
+ else:
+ # This replacing migration cannot be used because it is
+ # partially applied. Remove it from the graph and remap
+ # dependencies to it (#25945).
+ self.graph.remove_replacement_node(migration_key, migration.replaces)
+
def build_graph(self):
"""
Build a migration dependency graph using both the disk and database.
@@ -250,27 +272,8 @@ class MigrationLoader:
self.add_external_dependencies(key, migration)
# Carry out replacements where possible and if enabled.
if self.replace_migrations:
- for key, migration in self.replacements.items():
- # Get applied status of each of this migration's replacement
- # targets.
- applied_statuses = [
- (target in self.applied_migrations) for target in migration.replaces
- ]
- # The replacing migration is only marked as applied if all of
- # its replacement targets are.
- if all(applied_statuses):
- self.applied_migrations[key] = migration
- else:
- self.applied_migrations.pop(key, None)
- # A replacing migration can be used if either all or none of
- # its replacement targets have been applied.
- if all(applied_statuses) or (not any(applied_statuses)):
- self.graph.remove_replaced_nodes(key, migration.replaces)
- else:
- # This replacing migration cannot be used because it is
- # partially applied. Remove it from the graph and remap
- # dependencies to it (#25945).
- self.graph.remove_replacement_node(key, migration.replaces)
+ for migration_key in self.replacements.keys():
+ self.replace_migration(migration_key)
# Ensure the graph is consistent.
try:
self.graph.validate_consistency()