def history_list(): """ Based in: https://github.com/dmishe/django-south/blob/master/south/management/commands/migrate.py#L108 """ from south import migration from south.models import MigrationHistory ret = {} apps = migration.all_migrations() labels = [app.app_label() for app in migration.all_migrations()] applied_migrations = [] for mi in MigrationHistory.objects.filter(app_name__in=labels): applied_migrations.append('%s.%s' % (mi.app_name, mi.migration)) for app in apps: label = app.app_label() ret[label] = [] for mi in app: migration_name = mi.app_label() + "." + mi.name() applied = migration_name in applied_migrations ret[label].append({'name': mi.name(), 'applied': applied}) return ret
def _clear_south_cache(self): for mig in list(migration.all_migrations()): delattr(mig._application, "migrations") Migrations._clear_cache() for mig in list(migration.all_migrations()): for m in mig: m.calculate_dependencies() mig._dependencies_done = False
def has_pending_migrations(): """ Returns whether any models need to be migrated via python manage.py migrate. This will be the case if any migrations are present in apps, but not in the database. Shamelessly stolen from http://stackoverflow.com/questions/7089969/programmatically-check-whether-there-are-django-south-migrations-that-need-to-be """ apps = list(migration.all_migrations()) try: applied_migrations = list( MigrationHistory.objects.filter( app_name__in=[app.app_label() for app in apps])) except DatabaseError: transaction.rollback_unless_managed() return True # The table has not been created yet. applied_migrations = [ '%s.%s' % (mi.app_name, mi.migration) for mi in applied_migrations ] for app in apps: for app_migration in app: if app_migration.app_label() + "." + app_migration.name( ) not in applied_migrations: return True # No pending migrations. return False
def handle(self, *args, **options): verbosity = int(options.get('verbosity', '1')) assert django.VERSION < (1, 7) from south import migration from south.models import MigrationHistory try: MigrationHistory.objects.count() except OperationalError: return apps = list(migration.all_migrations()) applied_migrations = MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps]) applied_migrations = ['%s.%s' % (mi.app_name, mi.migration) for mi in applied_migrations] for app in apps: for app_migration in app: migration_name = '%s.%s' % (app_migration.app_label(), app_migration.name()) print migration_name, bool(migration_name in applied_migrations) if migration_name not in applied_migrations: result = migration.migrate_app( app, app_migration.name(), verbosity = verbosity, db_dry_run = True, ) if result is False: sys.exit('Migration %s failed.' % migration_name)
def test_all_migrations(self): app = migration.get_app("fakeapp") otherapp = migration.get_app("otherfakeapp") self.assertEqual( { app: { "0001_spam": migration.get_migration(app, "0001_spam"), "0002_eggs": migration.get_migration(app, "0002_eggs"), "0003_alter_spam": migration.get_migration(app, "0003_alter_spam"), }, otherapp: { "0001_first": migration.get_migration( otherapp, "0001_first"), "0002_second": migration.get_migration( otherapp, "0002_second"), "0003_third": migration.get_migration( otherapp, "0003_third"), }, }, migration.all_migrations(), )
def handle(self, **options): # Resolve dependencies Migrations.calculate_dependencies() print "digraph G {" # Print each app in a cluster #for migrations in all_migrations(): # print " subgraph %s {" % migrations.app_label() # # Nodes inside here are linked # print (" -> ".join(['"%s.%s"' % (migration.app_label(), migration.name()) for migration in migrations])) + ";" # print " }" # For every migration, print its links. for migrations in all_migrations(): for migration in migrations: for other in migration.dependencies: print '"%s.%s" -> "%s.%s"' % ( other.app_label(), other.name(), migration.app_label(), migration.name(), ) print "}"
def handle(self, app=None, target=None, **options): # Preserve original argumets to use in the finall migrate command call: _app = app _target = target # GUARD: If not auto-skip, just call south's migrate command: if not options.get('autoskip', False): return management.call_command('migrate', _app, _target, **options) # DUPLICATE OF 'south.mannagement.commands.migrate': # if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [migration.Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # END DUPE CODE # Prefore a fake first migration for all apps needing that: autoskip_first_migration(apps, **options) # Finally, preform the real migrations: management.call_command('migrate', _app, _target, **options)
def _clear_south_cache(self): for mig in list(migration.all_migrations()): try: delattr(mig._application, "migrations") except AttributeError: pass Migrations._clear_cache()
def handle(self, app=None, target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False, show_changes=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, **options): # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb # This code imports any module named 'management' in INSTALLED_APPS. # The 'management' module is the preferred way of listening to post_syncdb # signals, and since we're sending those out with create_table migrations, # we need apps to behave correctly. for app_name in settings.INSTALLED_APPS: try: import_module('.management', app_name) except ImportError as exc: msg = exc.args[0] if not msg.startswith('No module named') or 'management' not in msg: raise # END DJANGO DUPE CODE # if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print("The app '%s' does not appear to use migrations." % app) print("./manage.py migrate " + self.args) return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database, **options) if show_changes and apps: show_migration_changes(apps) if not (show_list or show_changes): for app in apps: result = migration.migrate_app( app, target_name=target, fake=fake, db_dry_run=db_dry_run, verbosity=int(options.get('verbosity', 0)), interactive=options.get('interactive', True), load_initial_data=not options.get('no_initial_data', False), merge=merge, skip=skip, database=database, delete_ghosts=delete_ghosts, ignore_ghosts=ignore_ghosts, ) if result is False: sys.exit(1) # Migration failed, so the command fails.
def handle(self, **options): # Resolve dependencies Migrations.calculate_dependencies() colors = ['crimson', 'darkgreen', 'darkgoldenrod', 'navy', 'brown', 'darkorange', 'aquamarine', 'blueviolet'] color_index = 0 wrapper = textwrap.TextWrapper(width=40) print("digraph G {") # Group each app in a subgraph for migrations in all_migrations(): print(" subgraph %s {" % migrations.app_label()) print(" node [color=%s];" % colors[color_index]) for migration in migrations: # Munge the label - text wrap and change _ to spaces label = "%s - %s" % ( migration.app_label(), migration.name()) label = re.sub(r"_+", " ", label) label = "\\n".join(wrapper.wrap(label)) print(' "%s.%s" [label="%s"];' % ( migration.app_label(), migration.name(), label)) print(" }") color_index = (color_index + 1) % len(colors) # For every migration, print its links. for migrations in all_migrations(): for migration in migrations: for other in migration.dependencies: # Added weight tends to keep migrations from the same app # in vertical alignment attrs = "[weight=2.0]" # But the more interesting edges are those between apps if other.app_label() != migration.app_label(): attrs = "[style=bold]" print(' "%s.%s" -> "%s.%s" %s;' % ( other.app_label(), other.name(), migration.app_label(), migration.name(), attrs )) print("}");
def handle(self, **options): # Resolve dependencies Migrations.calculate_dependencies() colors = [ 'crimson', 'darkgreen', 'darkgoldenrod', 'navy', 'brown', 'darkorange', 'aquamarine' , 'blueviolet' ] color_index = 0 wrapper = textwrap.TextWrapper(width=40) print("digraph G {") # Group each app in a subgraph for migrations in all_migrations(): print(" subgraph %s {" % migrations.app_label()) print(" node [color=%s];" % colors[color_index]) for migration in migrations: # Munge the label - text wrap and change _ to spaces label = "%s - %s" % ( migration.app_label(), migration.name()) label = re.sub(r"_+", " ", label) label= "\\n".join(wrapper.wrap(label)) print(' "%s.%s" [label="%s"];' % ( migration.app_label(), migration.name(), label)) print(" }") color_index = (color_index + 1) % len(colors) # For every migration, print its links. for migrations in all_migrations(): for migration in migrations: for other in migration.dependencies: # Added weight tends to keep migrations from the same app # in vertical alignment attrs = "[weight=2.0]" # But the more interesting edges are those between apps if other.app_label() != migration.app_label(): attrs = "[style=bold]" print(' "%s.%s" -> "%s.%s" %s;' % ( other.app_label(), other.name(), migration.app_label(), migration.name(), attrs )) print("}");
def test_all_migrations(self): app = migration.get_app("fakeapp") self.assertEqual( {app: { "0001_spam": migration.get_migration(app, "0001_spam"), "0002_eggs": migration.get_migration(app, "0002_eggs"), }}, migration.all_migrations(), )
def test_all_migrations(self): app = migration.get_app("fakeapp") self.assertEqual( {app: { "0001_spam": migration.get_migration(app, "0001_spam"), "0002_eggs": migration.get_migration(app, "0002_eggs"), "0003_alter_spam": migration.get_migration(app, "0003_alter_spam"), }}, migration.all_migrations(), )
def get_migrations_task(queue): from collections import defaultdict southified_apps = list(all_migrations()) available_migrations = defaultdict(list) for migration in itertools.chain.from_iterable(southified_apps): available_migrations[migration.app_label()].append(get_migration_location(migration)) applied_migrations = defaultdict(list) for history in MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in southified_apps]).order_by('migration'): migration = history.get_migration() applied_migrations[migration.app_label()].append(get_migration_location(migration)) queue.put((dict(available_migrations), dict(applied_migrations)))
def handle(self, app=None, **options): # DUPLICATE OF 'south.mannagement.commands.migrate': # Migrate each app if app: try: apps = [migration.Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # END DUPE CODE # Django 1.1 compatibility code: if DJANGO_VERSION[:3] >= (1, 2, 0): database = options.get('database', db.DEFAULT_DB_ALIAS) connection = db.connections[database] else: connection = db.connection # Get a list of installed tables: tables = connection.introspection.table_names() # Find apps where the first migration should be faked: autofake_apps = [] for app in apps: app_label = app.app_label() # GUARD: If there is migration history for this app, the first # migration should never be faked: if MigrationHistory.objects.filter(app_name=app_label, applied__isnull=False).count() > 0: continue # If one of the app's models have a table in the database, assume # that the first migration should be skipped for app: for model in db.models.get_models(db.models.get_app(app_label)): if model._meta.db_table in tables: autofake_apps.append(app_label) break # Prefore a fake first migration for all apps needing that: south_options = { 'fake': True, 'verbosity': options.get('verbosity'), 'db_dry_run': options.get('db_dry_run'), 'no_initial_data': not options.get('load_initial_data'), } target = options.get('first_migration') for app_label in autofake_apps: management.call_command('migrate', app_label, target, **south_options)
def fake_if_needed(self, verbosity=1): # detect installed models # (code borrowed from django syncdb command) tables = connection.introspection.table_names() def model_in_database(model): opts = model._meta converter = connection.introspection.table_name_converter return (converter(opts.db_table) in tables) or \ (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables) # list all applications with south migration # (code borrowed from south migrate command) from south import migration apps = list(migration.all_migrations()) applied_migrations = MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps]) applied_migrations_lookup = dict(('%s.%s' % (mi.app_name, mi.migration), mi) for mi in applied_migrations) if verbosity > 0: print 'Status after syncdb:' for app in apps: # for each app with migrations, list already applied migrations applied_migrations = [] for migration in app: full_name = migration.app_label() + "." + migration.name() if full_name in applied_migrations_lookup: applied_migration = applied_migrations_lookup[full_name] if applied_migration.applied: applied_migrations.append(migration.name()) # try all models in database, if there none, the application is new # (because south syncdb does not create any tables) new = True for m in models.get_models(app.get_application().models): if model_in_database(m): new = False break if new: status = 'application-is-new' elif not applied_migrations: status = 'migration-is-new' else: status = 'normal' if verbosity > 0: print ' - %s: %s' % (app.app_label(), status) if status == 'migration-is-new': if verbosity > 0: print ' need fake migration to 0001_initial' # migrate --fake gdc 0001 SouthMigrateCommand().execute(app=app.app_label(), target='0001', fake=True, verbosity=verbosity)
def _db_current(self): """Discover whether there are any outstanding migrations to be applied""" if not self._db_populated(): return False from south.models import MigrationHistory applied_migrations = MigrationHistory.objects.all().values('app_name', 'migration') applied_migrations = [(mh['app_name'], mh['migration']) for mh in applied_migrations] from south import migration for app_migrations in list(migration.all_migrations()): for m in app_migrations: if (m.app_label(), m.name()) not in applied_migrations: return False return True
def _count_migrations_1_4_db(db_name): from south.models import MigrationHistory from south.migration import all_migrations apps = all_migrations() applied_migrations = MigrationHistory.objects.filter( app_name__in=[app.app_label() for app in apps]) if db_name != DEFAULT_DB_ALIAS: applied_migrations = applied_migrations.using(db_name) applied_migrations_lookup = dict() nmigrations = 0 for app in apps: for migration in app: full_name = migration.app_label() + '.' + migration.name() if full_name not in applied_migrations_lookup: nmigrations += 1 return nmigrations
def test_all_migrations(self): app = migration.get_app("fakeapp") otherapp = migration.get_app("otherfakeapp") self.assertEqual({ app: { "0001_spam": migration.get_migration(app, "0001_spam"), "0002_eggs": migration.get_migration(app, "0002_eggs"), "0003_alter_spam": migration.get_migration(app, "0003_alter_spam"), }, otherapp: { "0001_first": migration.get_migration(otherapp, "0001_first"), "0002_second": migration.get_migration(otherapp, "0002_second"), "0003_third": migration.get_migration(otherapp, "0003_third"), }, }, migration.all_migrations(), )
def handle(*args, **kwargs): needs_migration = False apps = list(migration.all_migrations()) applied_migrations = [(x.app_name, x.migration) for x in list(MigrationHistory.objects.all())] for app in apps: for mi in app: app_label = mi.app_label() migration_name = mi.name() if (app_label, migration_name) not in applied_migrations: needs_migration = True print "Migration needed for %s: %s" % (app_label, migration_name) if needs_migration: print "Migration needed." sys.exit(1) else: print "No migration needed." sys.exit(0)
def has_pending_migrations(): """ Returns whether any models need to be migrated via python manage.py migrate. This will be the case if any migrations are present in apps, but not in the database. Shamelessly stolen from http://stackoverflow.com/questions/7089969/programmatically-check-whether-there-are-django-south-migrations-that-need-to-be """ apps = list(migration.all_migrations()) try: applied_migrations = list(MigrationHistory.objects.filter(app_name__in=[app.app_label() for app in apps])) except DatabaseError: transaction.rollback_unless_managed() return True # The table has not been created yet. applied_migrations = ['%s.%s' % (mi.app_name,mi.migration) for mi in applied_migrations] for app in apps: for app_migration in app: if app_migration.app_label() + "." + app_migration.name() not in applied_migrations: return True # No pending migrations. return False
def begin(self): """ Initialize the test environment then create the test database and switch the connection over to that database. """ import django from django.conf import settings from django.db import connection from django.core import management from django.test.utils import setup_test_environment use_south = 'south' in settings.INSTALLED_APPS if use_south: from south import migration from south.hacks import hacks try: self.original_db_name = settings.DATABASE_NAME except AttributeError: # Django > 1.2 self.original_db_name = settings.DATABASES['default']['NAME'] try: django.setup() # Django >= 1.7 except AttributeError: pass setup_test_environment() if use_south: management.get_commands() hacks.patch_flush_during_test_db_creation() connection.creation.create_test_db(self.verbosity) if use_south: for app in migration.all_migrations(): migration.migrate_app(app, verbosity=self.verbosity)
def handle(self, **options): # Resolve dependencies Migrations.calculate_dependencies() print "digraph G {" # Print each app in a cluster #for migrations in all_migrations(): # print " subgraph %s {" % migrations.app_label() # # Nodes inside here are linked # print (" -> ".join(['"%s.%s"' % (migration.app_label(), migration.name()) for migration in migrations])) + ";" # print " }" # For every migration, print its links. for migrations in all_migrations(): for migration in migrations: for other in migration.dependencies: print '"%s.%s" -> "%s.%s"' % ( other.app_label(), other.name(), migration.app_label(), migration.name(), ) print "}";
def _clear_south_cache(self): for mig in list(migration.all_migrations()): delattr(mig._application, "migrations") Migrations._clear_cache()
from operator import methodcaller from django.core.management import call_command from south.signals import post_migrate from south import migration # Get a list of all the apps that use migrations. APPS_TO_WAIT_FOR = map(methodcaller('app_label'), migration.all_migrations()) def load_static_data(app, **kwargs): global APPS_TO_WAIT_FOR APPS_TO_WAIT_FOR.remove(app) if len(APPS_TO_WAIT_FOR) == 0: print "Loading static fixtures..." call_command('loaddata', 'groups') post_migrate.connect(load_static_data)
class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--all', action='store_true', dest='all_apps', default=False, help='Run the specified migration for all apps.'), make_option( '--list', action='store_true', dest='show_list', default=False, help='List migrations noting those that have been applied'), make_option('--changes', action='store_true', dest='show_changes', default=False, help='List changes for migrations'), make_option('--skip', action='store_true', dest='skip', default=False, help='Will skip over out-of-order missing migrations'), make_option( '--merge', action='store_true', dest='merge', default=False, help= 'Will run out-of-order missing migrations as they are - no rollbacks.' ), make_option('--no-initial-data', action='store_true', dest='no_initial_data', default=False, help='Skips loading initial data if specified.'), make_option( '--fake', action='store_true', dest='fake', default=False, help= "Pretends to do the migrations, but doesn't actually execute them." ), make_option( '--db-dry-run', action='store_true', dest='db_dry_run', default=False, help= "Doesn't execute the SQL generated by the db methods, and doesn't store a record that the migration(s) occurred. Useful to test migrations before applying them." ), make_option( '--delete-ghost-migrations', action='store_true', dest='delete_ghosts', default=False, help= "Tells South to delete any 'ghost' migrations (ones in the database but not on disk)." ), make_option( '--ignore-ghost-migrations', action='store_true', dest='ignore_ghosts', default=False, help= "Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations." ), make_option( '--noinput', action='store_false', dest='interactive', default=True, help='Tells Django to NOT prompt the user for input of any kind.'), make_option('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' 'Defaults to the "default" database.'), ) if '--verbosity' not in [ opt.get_opt_string() for opt in BaseCommand.option_list ]: option_list += (make_option( '--verbosity', action='store', dest='verbosity', default='1', type='choice', choices=['0', '1', '2'], help= 'Verbosity level; 0=minimal output, 1=normal output, 2=all output' ), ) help = "Runs migrations for all apps." args = "[appname] [migrationname|zero] [--all] [--list] [--skip] [--merge] [--no-initial-data] [--fake] [--db-dry-run] [--database=dbalias]" def handle(self, app=None, target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False, show_changes=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, **options): # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb # This code imports any module named 'management' in INSTALLED_APPS. # The 'management' module is the preferred way of listening to post_syncdb # signals, and since we're sending those out with create_table migrations, # we need apps to behave correctly. for app_name in settings.INSTALLED_APPS: try: __import__(app_name + '.management', {}, {}, ['']) except ImportError, exc: msg = exc.args[0] if not msg.startswith( 'No module named') or 'management' not in msg: raise # END DJANGO DUPE CODE # if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database) if show_changes and apps: show_migration_changes(apps) if not (show_list or show_changes): for app in apps: result = migration.migrate_app( app, target_name=target, fake=fake, db_dry_run=db_dry_run, verbosity=int(options.get('verbosity', 0)), interactive=options.get('interactive', True), load_initial_data=not options.get('no_initial_data', False), merge=merge, skip=skip, database=database, delete_ghosts=delete_ghosts, ignore_ghosts=ignore_ghosts, ) if result is False: sys.exit(1) # Migration failed, so the command fails.
def handle(self, app=None, target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False, show_changes=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, **options): # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb # This code imports any module named 'management' in INSTALLED_APPS. # The 'management' module is the preferred way of listening to post_syncdb # signals, and since we're sending those out with create_table migrations, # we need apps to behave correctly. for app_name in settings.INSTALLED_APPS: try: import_module('.management', app_name) except ImportError as exc: msg = exc.args[0] if not msg.startswith( 'No module named') or 'management' not in msg: raise # END DJANGO DUPE CODE # if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print("The app '%s' does not appear to use migrations." % app) print("./manage.py migrate " + self.args) return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database, **options) if show_changes and apps: show_migration_changes(apps) if not (show_list or show_changes): for app in apps: result = migration.migrate_app( app, target_name=target, fake=fake, db_dry_run=db_dry_run, verbosity=int(options.get('verbosity', 0)), interactive=options.get('interactive', True), load_initial_data=not options.get('no_initial_data', False), merge=merge, skip=skip, database=database, delete_ghosts=delete_ghosts, ignore_ghosts=ignore_ghosts, ) if result is False: sys.exit(1) # Migration failed, so the command fails.
def handle(self, *args, **options): _auto = options.get('auto', False) # Loop through all give apps # Or fail as no apps are supplied. if len(args) <= 0: self.say("No apps supplied") exit(1) for a in args: try: module, app = self.app_label_to_app_module(a) #print "Objects", module, app except ImproperlyConfigured as (e): module, app = None, None self.say("App '%s' could not be found." % a) if app: me = self.migrations_exist(module) if me: self.say("Auto migrations for %s" % a) _auto = True else: self.say("New migrations for %s" % a) _auto = False if _auto == True: _initial = False else: _initial = True from django.core import management options.update({'initial': _initial, 'auto': _auto}) p = str(a) try: management.call_command('schemamigration', p, **options) finally: from south.migration import Migration, Migrations # Migrate each app if a: try: apps = [Migrations(a)] _s = 's' if len(apps) == 1: _s = '' print "Migrating %s app%s in '%s' " % (len(apps), _s, a) for app in apps: result = migration.migrate_app( apps, target_name=None, fake=options.get('fake', False), db_dry_run=options.get( 'db_dry_run', False), verbosity=int(options.get('verbosity', 0)), interactive=options.get( 'interactive', True), load_initial_data=not options.get( 'no_initial_data', False), merge=options.get('merge', True), skip=False, database=options.get( 'database', DEFAULT_DB_ALIAS), delete_ghosts=options.get( 'delete_ghosts', False), ignore_ghosts=options.get( 'ignore_ghosts', False), ) if result is False: sys.exit( 1 ) # Migration failed, so the command fails. except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations())
class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option('--all', action='store_true', dest='all_apps', default=False, help='Run the specified migration for all apps.'), make_option( '--list', action='store_true', dest='show_list', default=False, help='List migrations noting those that have been applied'), make_option('--changes', action='store_true', dest='show_changes', default=False, help='List changes for migrations'), make_option('--skip', action='store_true', dest='skip', default=False, help='Will skip over out-of-order missing migrations'), make_option( '--merge', action='store_true', dest='merge', default=False, help= 'Will run out-of-order missing migrations as they are - no rollbacks.' ), make_option('--no-initial-data', action='store_true', dest='no_initial_data', default=False, help='Skips loading initial data if specified.'), make_option( '--fake', action='store_true', dest='fake', default=False, help= "Pretends to do the migrations, but doesn't actually execute them." ), make_option( '--db-dry-run', action='store_true', dest='db_dry_run', default=False, help= "Doesn't execute the SQL generated by the db methods, and doesn't store a record that the migration(s) occurred. Useful to test migrations before applying them." ), make_option( '--delete-ghost-migrations', action='store_true', dest='delete_ghosts', default=False, help= "Tells South to delete any 'ghost' migrations (ones in the database but not on disk)." ), make_option( '--ignore-ghost-migrations', action='store_true', dest='ignore_ghosts', default=False, help= "Tells South to ignore any 'ghost' migrations (ones in the database but not on disk) and continue to apply new migrations." ), make_option( '--noinput', action='store_false', dest='interactive', default=True, help='Tells Django to NOT prompt the user for input of any kind.'), make_option('--database', action='store', dest='database', default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. ' 'Defaults to the "default" database.'), make_option( '--hack', # KA-LITE-MOD: needed for relaunch_external hack action="store_true", dest="hack", default=False, help="Flag that we're getting an external callback ", ), ) if '--verbosity' not in [ opt.get_opt_string() for opt in BaseCommand.option_list ]: option_list += (make_option( '--verbosity', action='store', dest='verbosity', default='1', type='choice', choices=['0', '1', '2'], help= 'Verbosity level; 0=minimal output, 1=normal output, 2=all output' ), ) help = "Runs migrations for all apps." args = "[appname] [migrationname|zero] [--all] [--list] [--skip] [--merge] [--no-initial-data] [--fake] [--db-dry-run] [--database=dbalias]" def relaunch_external(self): """ This is a KA Lite hack. #KA-LITE-MOD In our git-based update command (until version 0.10.3), we update the code, then run run the 'migrate' command under the old code (since it's loaded into memory). This can cause conflicting / now-outdated imports. The right thing to do is to run migrate via subprocess, so that it runs all fresh, new code. Alas, we've shipped versions that don't do this already, so we can't go back and fix. The hack here is: detect when this is happening, then force migrate to re-launch itself via subprocess. Note that this only works if this file (migrate.py) hasn't already been loaded into the process. It shouldn't be... but it's worth keeping in mind! """ import sys import settings import utils.django_utils.command reload( utils.django_utils.command ) # this is necessary because the 0.10.2 version of this code has a bug! # Launch through subprocess, then print output. sys.stdout.write( "[NOTE version upgrade hack: running 'migrate' through subprocess.]\n\n" ) sys.stdout.write( "Please wait. DO NOT CANCEL WHILE MIGRATE RUNS, EVEN THOUGH YOU'RE RECEIVING NO OUTPUT!! JUST WAIT!!\n" ) sys.stdout.write( "Output will print below when migrate is complete.\n\n") (out, err, rc) = utils.django_utils.command.call_outside_command_with_output( "migrate", merge=True, hack=True, manage_py_dir=settings.PROJECT_PATH) sys.stdout.write(out) if rc: sys.stderr.write(err) sys.exit(0) # abort the rest of the migrate / update command def handle(self, app=None, target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False, show_changes=False, database=DEFAULT_DB_ALIAS, delete_ghosts=False, ignore_ghosts=False, **options): if "update" in sys.argv and "--hack" not in sys.argv: self.relaunch_external() # NOTE: THIS IS DUPLICATED FROM django.core.management.commands.syncdb # This code imports any module named 'management' in INSTALLED_APPS. # The 'management' module is the preferred way of listening to post_syncdb # signals, and since we're sending those out with create_table migrations, # we need apps to behave correctly. for app_name in settings.INSTALLED_APPS: try: import_module('.management', app_name) except ImportError, exc: msg = exc.args[0] if not msg.startswith( 'No module named') or 'management' not in msg: raise # END DJANGO DUPE CODE # if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database, **options) if show_changes and apps: show_migration_changes(apps) if not (show_list or show_changes): for app in apps: result = migration.migrate_app( app, target_name=target, fake=fake, db_dry_run=db_dry_run, verbosity=int(options.get('verbosity', 0)), interactive=options.get('interactive', True), load_initial_data=not options.get('no_initial_data', False), merge=merge, skip=skip, database=database, delete_ghosts=delete_ghosts, ignore_ghosts=ignore_ghosts, ) if result is False: sys.exit(1) # Migration failed, so the command fails.
# if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database, **options) if not show_list: for app in apps: result = migration.migrate_app( app, target_name = target, fake = fake, db_dry_run = db_dry_run, verbosity = int(options.get('verbosity', 0)), interactive = options.get('interactive', True),
def handle(self, *args, **options): _auto = options.get('auto', False) # Loop through all give apps # Or fail as no apps are supplied. if len(args) <= 0: self.say("No apps supplied") exit(1) for a in args: try: module, app = self.app_label_to_app_module(a) #print "Objects", module, app except ImproperlyConfigured as (e): module, app = None, None self.say("App '%s' could not be found." % a) if app: me = self.migrations_exist(module) if me: self.say("Auto migrations for %s" % a) _auto = True else: self.say("New migrations for %s" % a) _auto = False if _auto == True: _initial = False else: _initial = True from django.core import management options.update({'initial':_initial, 'auto':_auto}) p = str(a) try: management.call_command('schemamigration', p, **options) finally: from south.migration import Migration, Migrations # Migrate each app if a: try: apps = [Migrations(a)] _s = 's' if len(apps) == 1: _s = '' print "Migrating %s app%s in '%s' " % (len(apps), _s, a) for app in apps: result = migration.migrate_app( apps, target_name = None, fake = options.get('fake', False), db_dry_run = options.get('db_dry_run', False), verbosity = int(options.get('verbosity', 0)), interactive = options.get('interactive', True), load_initial_data = not options.get('no_initial_data', False), merge = options.get('merge', True), skip = False, database = options.get('database', DEFAULT_DB_ALIAS), delete_ghosts = options.get('delete_ghosts', False), ignore_ghosts = options.get('ignore_ghosts', False), ) if result is False: sys.exit(1) # Migration failed, so the command fails. except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations())
# if all_apps flag is set, shift app over to target if options.get('all_apps', False): target = app app = None # Migrate each app if app: try: apps = [Migrations(app)] except NoMigrations: print "The app '%s' does not appear to use migrations." % app print "./manage.py migrate " + self.args return else: apps = list(migration.all_migrations()) # Do we need to show the list of migrations? if show_list and apps: list_migrations(apps, database, **options) if not show_list: for app in apps: result = migration.migrate_app( app, target_name=target, fake=fake, db_dry_run=db_dry_run, verbosity=int(options.get('verbosity', 0)), interactive=options.get('interactive', True),