Browse Source

Fixed #31516 -- Improved naming of migrations with multiple operations.

52 gives 60 in total (52 + 5 + 3).

Co-authored-by: Adam Johnson <me@adamj.eu>
manav014 4 years ago
parent
commit
99640e24b4
2 changed files with 57 additions and 12 deletions
  1. 13 11
      django/db/migrations/migration.py
  2. 44 1
      tests/migrations/test_autodetector.py

+ 13 - 11
django/db/migrations/migration.py

@@ -1,4 +1,3 @@
-from django.db.migrations import operations
 from django.db.migrations.utils import get_migration_name_timestamp
 from django.db.transaction import atomic
 
@@ -186,16 +185,19 @@ class Migration:
         if self.initial:
             return 'initial'
 
-        name = None
-        if len(self.operations) == 1:
-            name = self.operations[0].migration_name_fragment
-        elif (
-            len(self.operations) > 1 and
-            all(isinstance(o, operations.CreateModel) for o in self.operations)
-        ):
-            name = '_'.join(sorted(o.migration_name_fragment for o in self.operations))
-        if name is None:
-            name = 'auto_%s' % get_migration_name_timestamp()
+        raw_fragments = [op.migration_name_fragment for op in self.operations]
+        fragments = [name for name in raw_fragments if name]
+
+        if not fragments or len(fragments) != len(self.operations):
+            return 'auto_%s' % get_migration_name_timestamp()
+
+        name = fragments[0]
+        for fragment in fragments[1:]:
+            new_name = f'{name}_{fragment}'
+            if len(new_name) > 52:
+                name = f'{name}_and_more'
+                break
+            name = new_name
         return name
 
 

+ 44 - 1
tests/migrations/test_autodetector.py

@@ -2661,6 +2661,23 @@ class MigrationSuggestNameTests(SimpleTestCase):
         migration = Migration('0002_initial', 'test_app')
         self.assertEqual(migration.suggest_name(), 'delete_person')
 
+    def test_single_operation_long_name(self):
+        class Migration(migrations.Migration):
+            operations = [migrations.CreateModel('A' * 53, fields=[])]
+
+        migration = Migration('some_migration', 'test_app')
+        self.assertEqual(migration.suggest_name(), 'a' * 53)
+
+    def test_two_operations(self):
+        class Migration(migrations.Migration):
+            operations = [
+                migrations.CreateModel('Person', fields=[]),
+                migrations.DeleteModel('Animal'),
+            ]
+
+        migration = Migration('some_migration', 'test_app')
+        self.assertEqual(migration.suggest_name(), 'person_delete_animal')
+
     def test_two_create_models(self):
         class Migration(migrations.Migration):
             operations = [
@@ -2669,7 +2686,7 @@ class MigrationSuggestNameTests(SimpleTestCase):
             ]
 
         migration = Migration('0001_initial', 'test_app')
-        self.assertEqual(migration.suggest_name(), 'animal_person')
+        self.assertEqual(migration.suggest_name(), 'person_animal')
 
     def test_two_create_models_with_initial_true(self):
         class Migration(migrations.Migration):
@@ -2682,6 +2699,32 @@ class MigrationSuggestNameTests(SimpleTestCase):
         migration = Migration('0001_initial', 'test_app')
         self.assertEqual(migration.suggest_name(), 'initial')
 
+    def test_many_operations_suffix(self):
+        class Migration(migrations.Migration):
+            operations = [
+                migrations.CreateModel('Person1', fields=[]),
+                migrations.CreateModel('Person2', fields=[]),
+                migrations.CreateModel('Person3', fields=[]),
+                migrations.DeleteModel('Person4'),
+                migrations.DeleteModel('Person5'),
+            ]
+
+        migration = Migration('some_migration', 'test_app')
+        self.assertEqual(
+            migration.suggest_name(),
+            'person1_person2_person3_delete_person4_and_more',
+        )
+
+    def test_operation_with_no_suggested_name(self):
+        class Migration(migrations.Migration):
+            operations = [
+                migrations.CreateModel('Person', fields=[]),
+                migrations.RunSQL('SELECT 1 FROM person;'),
+            ]
+
+        migration = Migration('some_migration', 'test_app')
+        self.assertIs(migration.suggest_name().startswith('auto_'), True)
+
     def test_none_name(self):
         class Migration(migrations.Migration):
             operations = [migrations.RunSQL('SELECT 1 FROM person;')]