summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelvyn Sopacua <m.r.sopacua@gmail.com>2017-02-20 15:45:20 +0100
committerTim Graham <timograham@gmail.com>2017-07-26 13:47:35 -0400
commit5bb9b9a3881fb1a334efb2c1357a20bdce68a960 (patch)
tree3d066ba8c7f55ba66e7babcf9e2e559bfb334845
parent5ccbcc5bf61c746a1d5ec2b3d2e0dc56c1a63fe0 (diff)
Fixed #28363 -- Allowed naming the migration generated by squashmigrations.
-rw-r--r--django/core/management/commands/squashmigrations.py17
-rw-r--r--docs/ref/django-admin.txt7
-rw-r--r--docs/releases/2.0.txt3
-rw-r--r--docs/topics/migrations.txt3
-rw-r--r--tests/migrations/test_commands.py22
5 files changed, 49 insertions, 3 deletions
diff --git a/django/core/management/commands/squashmigrations.py b/django/core/management/commands/squashmigrations.py
index a784bfb345..60faf6cc1f 100644
--- a/django/core/management/commands/squashmigrations.py
+++ b/django/core/management/commands/squashmigrations.py
@@ -32,6 +32,10 @@ class Command(BaseCommand):
'--noinput', '--no-input', action='store_false', dest='interactive',
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):
@@ -41,6 +45,7 @@ class Command(BaseCommand):
start_migration_name = options['start_migration_name']
migration_name = options['migration_name']
no_optimize = options['no_optimize']
+ squashed_name = options['squashed_name']
# Load the current graph state, check the app and migration they asked for exists
loader = MigrationLoader(connections[DEFAULT_DB_ALIAS])
@@ -154,9 +159,17 @@ class Command(BaseCommand):
"replaces": replaces,
})
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:
+ # Generate a name.
+ name = '%s_squashed_%s' % (start_migration.name, migration.name)
+ new_migration = subclass(name, app_label)
else:
- new_migration = subclass("0001_squashed_%s" % migration.name, app_label)
+ name = '0001_%s' % (squashed_name or 'squashed_%s' % migration.name)
+ new_migration = subclass(name, app_label)
new_migration.initial = True
# Write out the new migration file
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 20e1bb02de..3a83bd2b7d 100644
--- a/docs/ref/django-admin.txt
+++ b/docs/ref/django-admin.txt
@@ -1132,6 +1132,13 @@ behavior, as optimization is meant to be safe.
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``
------------
diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt
index 0757d834f9..36359e4979 100644
--- a/docs/releases/2.0.txt
+++ b/docs/releases/2.0.txt
@@ -219,7 +219,8 @@ Management Commands
Migrations
~~~~~~~~~~
-* ...
+* The new :option:`squashmigrations --squashed-name` option allows naming
+ the squashed migration.
Models
~~~~~~
diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt
index a2eae4ff3d..6f0e3b912e 100644
--- a/docs/topics/migrations.txt
+++ b/docs/topics/migrations.txt
@@ -605,6 +605,9 @@ work::
all instances of the codebase have applied the migrations you squashed,
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
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),
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 777081e3c7..3e4f7b5410 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -1356,3 +1356,25 @@ class SquashMigrationsTests(MigrationTestBase):
)
with self.assertRaisesMessage(CommandError, msg):
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))