Browse Source

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

Melvyn Sopacua 8 years ago
parent
commit
5bb9b9a388

+ 15 - 2
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

+ 7 - 0
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``
 ------------
 

+ 2 - 1
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
 ~~~~~~

+ 3 - 0
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),

+ 22 - 0
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))