Loading django/core/management/commands/migrate.py +45 −1 Original line number Diff line number Diff line # encoding: utf8 from __future__ import unicode_literals from optparse import make_option from collections import OrderedDict from importlib import import_module Loading @@ -11,7 +13,7 @@ from django.core.management.color import no_style from django.core.management.sql import custom_sql_for_model, emit_post_migrate_signal, emit_pre_migrate_signal from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS from django.db.migrations.executor import MigrationExecutor from django.db.migrations.loader import AmbiguityError from django.db.migrations.loader import MigrationLoader, AmbiguityError from django.utils.module_loading import module_has_submodule Loading @@ -26,6 +28,8 @@ class Command(BaseCommand): 'Defaults to the "default" database.'), make_option('--fake', action='store_true', dest='fake', default=False, help='Mark migrations as run without actually running them'), make_option('--list', action='store_true', dest='list', default=False, help='Show a list of all known migrations and which are applied'), ) help = "Updates database schema. Manages both apps with migrations and those without." Loading @@ -48,6 +52,10 @@ class Command(BaseCommand): db = options.get('database') connection = connections[db] # If they asked for a migration listing, quit main execution flow and show it if options.get("list", False): return self.show_migration_list(connection, args) # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) Loading Loading @@ -243,3 +251,39 @@ class Command(BaseCommand): call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=connection.alias, skip_validation=True) return created_models def show_migration_list(self, connection, apps=None): """ Shows a list of all migrations on the system, or only those of some named apps. """ # Load migrations from disk/DB loader = MigrationLoader(connection) graph = loader.graph # If we were passed a list of apps, validate it if apps: invalid_apps = [] for app in apps: if app_label not in loader.migrated_apps: invalid_apps.append(app) if invalid_apps: raise CommandError("No migrations present for: %s" % (", ".join(invalid_apps))) # Otherwise, show all apps in alphabetic order else: apps = sorted(loader.migrated_apps) # For each app, print its migrations in order from oldest (roots) to # newest (leaves). for app in apps: self.stdout.write(app, self.style.MIGRATE_LABEL) shown = set() for node in graph.leaf_nodes(app): for plan_node in graph.forwards_plan(node): if plan_node not in shown and plan_node[0] == app: if plan_node in loader.applied_migrations: self.stdout.write(" [X] %s" % plan_node[1]) else: self.stdout.write(" [ ] %s" % plan_node[1]) shown.add(plan_node) # If we didn't print anything, then a small message if not shown: self.stdout.write(" (no migrations)", self.style.MIGRATE_FAILURE) django/db/migrations/graph.py +2 −2 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class MigrationGraph(object): roots.add(node) return roots def leaf_nodes(self): def leaf_nodes(self, app=None): """ Returns all leaf nodes - that is, nodes with no dependents in their app. These are the "most current" version of an app's schema. Loading @@ -84,7 +84,7 @@ class MigrationGraph(object): """ leaves = set() for node in self.nodes: if not any(key[0] == node[0] for key in self.dependents.get(node, set())): if not any(key[0] == node[0] for key in self.dependents.get(node, set())) and (not app or app == node[0]): leaves.add(node) return leaves Loading Loading
django/core/management/commands/migrate.py +45 −1 Original line number Diff line number Diff line # encoding: utf8 from __future__ import unicode_literals from optparse import make_option from collections import OrderedDict from importlib import import_module Loading @@ -11,7 +13,7 @@ from django.core.management.color import no_style from django.core.management.sql import custom_sql_for_model, emit_post_migrate_signal, emit_pre_migrate_signal from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS from django.db.migrations.executor import MigrationExecutor from django.db.migrations.loader import AmbiguityError from django.db.migrations.loader import MigrationLoader, AmbiguityError from django.utils.module_loading import module_has_submodule Loading @@ -26,6 +28,8 @@ class Command(BaseCommand): 'Defaults to the "default" database.'), make_option('--fake', action='store_true', dest='fake', default=False, help='Mark migrations as run without actually running them'), make_option('--list', action='store_true', dest='list', default=False, help='Show a list of all known migrations and which are applied'), ) help = "Updates database schema. Manages both apps with migrations and those without." Loading @@ -48,6 +52,10 @@ class Command(BaseCommand): db = options.get('database') connection = connections[db] # If they asked for a migration listing, quit main execution flow and show it if options.get("list", False): return self.show_migration_list(connection, args) # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) Loading Loading @@ -243,3 +251,39 @@ class Command(BaseCommand): call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=connection.alias, skip_validation=True) return created_models def show_migration_list(self, connection, apps=None): """ Shows a list of all migrations on the system, or only those of some named apps. """ # Load migrations from disk/DB loader = MigrationLoader(connection) graph = loader.graph # If we were passed a list of apps, validate it if apps: invalid_apps = [] for app in apps: if app_label not in loader.migrated_apps: invalid_apps.append(app) if invalid_apps: raise CommandError("No migrations present for: %s" % (", ".join(invalid_apps))) # Otherwise, show all apps in alphabetic order else: apps = sorted(loader.migrated_apps) # For each app, print its migrations in order from oldest (roots) to # newest (leaves). for app in apps: self.stdout.write(app, self.style.MIGRATE_LABEL) shown = set() for node in graph.leaf_nodes(app): for plan_node in graph.forwards_plan(node): if plan_node not in shown and plan_node[0] == app: if plan_node in loader.applied_migrations: self.stdout.write(" [X] %s" % plan_node[1]) else: self.stdout.write(" [ ] %s" % plan_node[1]) shown.add(plan_node) # If we didn't print anything, then a small message if not shown: self.stdout.write(" (no migrations)", self.style.MIGRATE_FAILURE)
django/db/migrations/graph.py +2 −2 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ class MigrationGraph(object): roots.add(node) return roots def leaf_nodes(self): def leaf_nodes(self, app=None): """ Returns all leaf nodes - that is, nodes with no dependents in their app. These are the "most current" version of an app's schema. Loading @@ -84,7 +84,7 @@ class MigrationGraph(object): """ leaves = set() for node in self.nodes: if not any(key[0] == node[0] for key in self.dependents.get(node, set())): if not any(key[0] == node[0] for key in self.dependents.get(node, set())) and (not app or app == node[0]): leaves.add(node) return leaves Loading