summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/core/management/commands/migrate.py43
1 files changed, 42 insertions, 1 deletions
diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py
index 1e407831b4..299edbe421 100644
--- a/django/core/management/commands/migrate.py
+++ b/django/core/management/commands/migrate.py
@@ -16,6 +16,7 @@ from django.db.migrations.executor import MigrationExecutor
from django.db.migrations.loader import AmbiguityError
from django.db.migrations.state import ModelState, ProjectState
from django.utils.module_loading import module_has_submodule
+from django.utils.text import Truncator
class Command(BaseCommand):
@@ -51,6 +52,10 @@ class Command(BaseCommand):
'flag. Django will only check for an existing table name.',
)
parser.add_argument(
+ '--plan', action='store_true',
+ help='Shows a list of the migration actions that will be performed.',
+ )
+ parser.add_argument(
'--run-syncdb', action='store_true',
help='Creates tables for apps without migrations.',
)
@@ -134,8 +139,20 @@ class Command(BaseCommand):
targets = executor.loader.graph.leaf_nodes()
plan = executor.migration_plan(targets)
- run_syncdb = options['run_syncdb'] and executor.loader.unmigrated_apps
+ if options['plan']:
+ self.stdout.write('Planned operations:', self.style.MIGRATE_LABEL)
+ if not plan:
+ self.stdout.write(' No planned migration operations.')
+ for migration, backwards in plan:
+ self.stdout.write(str(migration), self.style.MIGRATE_HEADING)
+ for operation in migration.operations:
+ message, is_error = self.describe_operation(operation, backwards)
+ style = self.style.WARNING if is_error else None
+ self.stdout.write(' ' + message, style)
+ return
+
+ run_syncdb = options['run_syncdb'] and executor.loader.unmigrated_apps
# Print some useful info
if self.verbosity >= 1:
self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:"))
@@ -309,3 +326,27 @@ class Command(BaseCommand):
# Deferred SQL is executed when exiting the editor's context.
if self.verbosity >= 1:
self.stdout.write(" Running deferred SQL...\n")
+
+ @staticmethod
+ def describe_operation(operation, backwards):
+ """Return a string that describes a migration operation for --plan."""
+ prefix = ''
+ if hasattr(operation, 'code'):
+ code = operation.reverse_code if backwards else operation.code
+ action = code.__doc__ if code else ''
+ elif hasattr(operation, 'sql'):
+ action = operation.reverse_sql if backwards else operation.sql
+ else:
+ action = ''
+ if backwards:
+ prefix = 'Undo '
+ if action is None:
+ action = 'IRREVERSIBLE'
+ is_error = True
+ else:
+ action = action.replace('\n', '')
+ is_error = False
+ if action:
+ action = ' -> ' + action
+ truncated = Truncator(action)
+ return prefix + operation.describe() + truncated.chars(40), is_error