You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sqlmigrate.py 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from django.apps import apps
  2. from django.core.management.base import BaseCommand, CommandError
  3. from django.db import DEFAULT_DB_ALIAS, connections
  4. from django.db.migrations.executor import MigrationExecutor
  5. from django.db.migrations.loader import AmbiguityError
  6. class Command(BaseCommand):
  7. help = "Prints the SQL statements for the named migration."
  8. output_transaction = True
  9. def add_arguments(self, parser):
  10. parser.add_argument('app_label', help='App label of the application containing the migration.')
  11. parser.add_argument('migration_name', help='Migration name to print the SQL for.')
  12. parser.add_argument(
  13. '--database', default=DEFAULT_DB_ALIAS,
  14. help='Nominates a database to create SQL for. Defaults to the "default" database.',
  15. )
  16. parser.add_argument(
  17. '--backwards', action='store_true',
  18. help='Creates SQL to unapply the migration, rather than to apply it',
  19. )
  20. def execute(self, *args, **options):
  21. # sqlmigrate doesn't support coloring its output but we need to force
  22. # no_color=True so that the BEGIN/COMMIT statements added by
  23. # output_transaction don't get colored either.
  24. options['no_color'] = True
  25. return super().execute(*args, **options)
  26. def handle(self, *args, **options):
  27. # Get the database we're operating from
  28. connection = connections[options['database']]
  29. # Load up an executor to get all the migration data
  30. executor = MigrationExecutor(connection)
  31. # Resolve command-line arguments into a migration
  32. app_label, migration_name = options['app_label'], options['migration_name']
  33. # Validate app_label
  34. try:
  35. apps.get_app_config(app_label)
  36. except LookupError as err:
  37. raise CommandError(str(err))
  38. if app_label not in executor.loader.migrated_apps:
  39. raise CommandError("App '%s' does not have migrations" % app_label)
  40. try:
  41. migration = executor.loader.get_migration_by_prefix(app_label, migration_name)
  42. except AmbiguityError:
  43. raise CommandError("More than one migration matches '%s' in app '%s'. Please be more specific." % (
  44. migration_name, app_label))
  45. except KeyError:
  46. raise CommandError("Cannot find a migration matching '%s' from app '%s'. Is it in INSTALLED_APPS?" % (
  47. migration_name, app_label))
  48. targets = [(app_label, migration.name)]
  49. # Show begin/end around output only for atomic migrations
  50. self.output_transaction = migration.atomic
  51. # Make a plan that represents just the requested migrations and show SQL
  52. # for it
  53. plan = [(executor.loader.graph.nodes[targets[0]], options['backwards'])]
  54. sql_statements = executor.collect_sql(plan)
  55. return '\n'.join(sql_statements)