Fixed #28363 -- Allowed naming the migration generated by squashmigrations.

This commit is contained in:
Melvyn Sopacua 2017-02-20 15:45:20 +01:00 committed by Tim Graham
parent 5ccbcc5bf6
commit 5bb9b9a388
5 changed files with 49 additions and 3 deletions

View File

@ -32,6 +32,10 @@ class Command(BaseCommand):
'--noinput', '--no-input', action='store_false', dest='interactive', '--noinput', '--no-input', action='store_false', dest='interactive',
help='Tells Django to NOT prompt the user for input of any kind.', help='Tells Django to NOT prompt the user for input of any kind.',
) )
parser.add_argument(
'--squashed-name', dest='squashed_name',
help='Sets the name of the new squashed migration.',
)
def handle(self, **options): def handle(self, **options):
@ -41,6 +45,7 @@ class Command(BaseCommand):
start_migration_name = options['start_migration_name'] start_migration_name = options['start_migration_name']
migration_name = options['migration_name'] migration_name = options['migration_name']
no_optimize = options['no_optimize'] no_optimize = options['no_optimize']
squashed_name = options['squashed_name']
# Load the current graph state, check the app and migration they asked for exists # Load the current graph state, check the app and migration they asked for exists
loader = MigrationLoader(connections[DEFAULT_DB_ALIAS]) loader = MigrationLoader(connections[DEFAULT_DB_ALIAS])
@ -154,9 +159,17 @@ class Command(BaseCommand):
"replaces": replaces, "replaces": replaces,
}) })
if start_migration_name: if start_migration_name:
new_migration = subclass("%s_squashed_%s" % (start_migration.name, migration.name), app_label) if squashed_name:
# Use the name from --squashed-name.
prefix, _ = start_migration.name.split('_', 1)
name = '%s_%s' % (prefix, squashed_name)
else: else:
new_migration = subclass("0001_squashed_%s" % migration.name, app_label) # Generate a name.
name = '%s_squashed_%s' % (start_migration.name, migration.name)
new_migration = subclass(name, app_label)
else:
name = '0001_%s' % (squashed_name or 'squashed_%s' % migration.name)
new_migration = subclass(name, app_label)
new_migration.initial = True new_migration.initial = True
# Write out the new migration file # Write out the new migration file

View File

@ -1132,6 +1132,13 @@ behavior, as optimization is meant to be safe.
Suppresses all user prompts. Suppresses all user prompts.
.. django-admin-option:: --squashed-name SQUASHED_NAME
.. versionadded:: 2.0
Sets the name of the squashed migration. When omitted, the name is based on the
first and last migration, with ``_squashed_`` in between.
``startapp`` ``startapp``
------------ ------------

View File

@ -219,7 +219,8 @@ Management Commands
Migrations Migrations
~~~~~~~~~~ ~~~~~~~~~~
* ... * The new :option:`squashmigrations --squashed-name` option allows naming
the squashed migration.
Models Models
~~~~~~ ~~~~~~

View File

@ -605,6 +605,9 @@ work::
all instances of the codebase have applied the migrations you squashed, all instances of the codebase have applied the migrations you squashed,
you can delete them. you can delete them.
Use the :option:`squashmigrations --squashed-name` option if you want to set
the name of the squashed migration rather than use an autogenerated one.
Note that model interdependencies in Django can get very complex, and squashing Note that model interdependencies in Django can get very complex, and squashing
may result in migrations that do not run; either mis-optimized (in which case may result in migrations that do not run; either mis-optimized (in which case
you can try again with ``--no-optimize``, though you should also report an issue), you can try again with ``--no-optimize``, though you should also report an issue),

View File

@ -1356,3 +1356,25 @@ class SquashMigrationsTests(MigrationTestBase):
) )
with self.assertRaisesMessage(CommandError, msg): with self.assertRaisesMessage(CommandError, msg):
call_command("squashmigrations", "migrations", "0003", "0002", interactive=False, verbosity=0) call_command("squashmigrations", "migrations", "0003", "0002", interactive=False, verbosity=0)
def test_squashed_name_with_start_migration_name(self):
"""--squashed-name specifies the new migration's name."""
squashed_name = 'squashed_name'
with self.temporary_migration_module(module='migrations.test_migrations') as migration_dir:
call_command(
'squashmigrations', 'migrations', '0001', '0002',
squashed_name=squashed_name, interactive=False, verbosity=0,
)
squashed_migration_file = os.path.join(migration_dir, '0001_%s.py' % squashed_name)
self.assertTrue(os.path.exists(squashed_migration_file))
def test_squashed_name_without_start_migration_name(self):
"""--squashed-name also works if a start migration is omitted."""
squashed_name = 'squashed_name'
with self.temporary_migration_module(module="migrations.test_migrations") as migration_dir:
call_command(
'squashmigrations', 'migrations', '0001',
squashed_name=squashed_name, interactive=False, verbosity=0,
)
squashed_migration_file = os.path.join(migration_dir, '0001_%s.py' % squashed_name)
self.assertTrue(os.path.exists(squashed_migration_file))