mirror of https://github.com/django/django.git
Refs #31703 -- Moved MigrationAutodetector.suggest_name() to Migration.
Allows expanding the method to inspect additional attributes of the migration instance. For example, the Migration.initial attribute.
This commit is contained in:
parent
798835112d
commit
bce180dd05
|
@ -9,9 +9,7 @@ from django.db.migrations.migration import Migration
|
||||||
from django.db.migrations.operations.models import AlterModelOptions
|
from django.db.migrations.operations.models import AlterModelOptions
|
||||||
from django.db.migrations.optimizer import MigrationOptimizer
|
from django.db.migrations.optimizer import MigrationOptimizer
|
||||||
from django.db.migrations.questioner import MigrationQuestioner
|
from django.db.migrations.questioner import MigrationQuestioner
|
||||||
from django.db.migrations.utils import (
|
from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject
|
||||||
COMPILED_REGEX_TYPE, RegexObject, get_migration_name_timestamp,
|
|
||||||
)
|
|
||||||
from django.utils.topological_sort import stable_topological_sort
|
from django.utils.topological_sort import stable_topological_sort
|
||||||
|
|
||||||
|
|
||||||
|
@ -1265,13 +1263,14 @@ class MigrationAutodetector:
|
||||||
for i, migration in enumerate(migrations):
|
for i, migration in enumerate(migrations):
|
||||||
if i == 0 and app_leaf:
|
if i == 0 and app_leaf:
|
||||||
migration.dependencies.append(app_leaf)
|
migration.dependencies.append(app_leaf)
|
||||||
if i == 0 and not app_leaf:
|
new_name_parts = ['%04i' % next_number]
|
||||||
new_name = "0001_%s" % migration_name if migration_name else "0001_initial"
|
if migration_name:
|
||||||
|
new_name_parts.append(migration_name)
|
||||||
|
elif i == 0 and not app_leaf:
|
||||||
|
new_name_parts.append('initial')
|
||||||
else:
|
else:
|
||||||
new_name = "%04i_%s" % (
|
new_name_parts.append(migration.suggest_name()[:100])
|
||||||
next_number,
|
new_name = '_'.join(new_name_parts)
|
||||||
migration_name or self.suggest_name(migration.operations)[:100],
|
|
||||||
)
|
|
||||||
name_map[(app_label, migration.name)] = (app_label, new_name)
|
name_map[(app_label, migration.name)] = (app_label, new_name)
|
||||||
next_number += 1
|
next_number += 1
|
||||||
migration.name = new_name
|
migration.name = new_name
|
||||||
|
@ -1306,22 +1305,6 @@ class MigrationAutodetector:
|
||||||
del changes[app_label]
|
del changes[app_label]
|
||||||
return changes
|
return changes
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def suggest_name(cls, ops):
|
|
||||||
"""
|
|
||||||
Given a set of operations, suggest a name for the migration they might
|
|
||||||
represent. Names are not guaranteed to be unique, but put some effort
|
|
||||||
into the fallback name to avoid VCS conflicts if possible.
|
|
||||||
"""
|
|
||||||
name = None
|
|
||||||
if len(ops) == 1:
|
|
||||||
name = ops[0].migration_name_fragment
|
|
||||||
elif len(ops) > 1 and all(isinstance(o, operations.CreateModel) for o in ops):
|
|
||||||
name = '_'.join(sorted(o.migration_name_fragment for o in ops))
|
|
||||||
if name is None:
|
|
||||||
name = 'auto_%s' % get_migration_name_timestamp()
|
|
||||||
return name
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_number(cls, name):
|
def parse_number(cls, name):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from django.db.migrations import operations
|
||||||
|
from django.db.migrations.utils import get_migration_name_timestamp
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
|
|
||||||
from .exceptions import IrreversibleError
|
from .exceptions import IrreversibleError
|
||||||
|
@ -175,6 +177,24 @@ class Migration:
|
||||||
operation.database_backwards(self.app_label, schema_editor, from_state, to_state)
|
operation.database_backwards(self.app_label, schema_editor, from_state, to_state)
|
||||||
return project_state
|
return project_state
|
||||||
|
|
||||||
|
def suggest_name(self):
|
||||||
|
"""
|
||||||
|
Suggest a name for the operations this migration might represent. Names
|
||||||
|
are not guaranteed to be unique, but put some effort into the fallback
|
||||||
|
name to avoid VCS conflicts if possible.
|
||||||
|
"""
|
||||||
|
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()
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
class SwappableTuple(tuple):
|
class SwappableTuple(tuple):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2481,25 +2481,39 @@ class AutodetectorTests(TestCase):
|
||||||
self.assertOperationAttributes(changes, 'app', 0, 1, name='book')
|
self.assertOperationAttributes(changes, 'app', 0, 1, name='book')
|
||||||
|
|
||||||
|
|
||||||
class AutodetectorSuggestNameTests(SimpleTestCase):
|
class MigrationSuggestNameTests(SimpleTestCase):
|
||||||
def test_single_operation(self):
|
def test_single_operation(self):
|
||||||
ops = [migrations.CreateModel('Person', fields=[])]
|
class Migration(migrations.Migration):
|
||||||
self.assertEqual(MigrationAutodetector.suggest_name(ops), 'person')
|
operations = [migrations.CreateModel('Person', fields=[])]
|
||||||
ops = [migrations.DeleteModel('Person')]
|
|
||||||
self.assertEqual(MigrationAutodetector.suggest_name(ops), 'delete_person')
|
migration = Migration('0001_initial', 'test_app')
|
||||||
|
self.assertEqual(migration.suggest_name(), 'person')
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
operations = [migrations.DeleteModel('Person')]
|
||||||
|
|
||||||
|
migration = Migration('0002_initial', 'test_app')
|
||||||
|
self.assertEqual(migration.suggest_name(), 'delete_person')
|
||||||
|
|
||||||
def test_two_create_models(self):
|
def test_two_create_models(self):
|
||||||
ops = [
|
class Migration(migrations.Migration):
|
||||||
migrations.CreateModel('Person', fields=[]),
|
operations = [
|
||||||
migrations.CreateModel('Animal', fields=[]),
|
migrations.CreateModel('Person', fields=[]),
|
||||||
]
|
migrations.CreateModel('Animal', fields=[]),
|
||||||
self.assertEqual(MigrationAutodetector.suggest_name(ops), 'animal_person')
|
]
|
||||||
|
|
||||||
|
migration = Migration('0001_initial', 'test_app')
|
||||||
|
self.assertEqual(migration.suggest_name(), 'animal_person')
|
||||||
|
|
||||||
def test_none_name(self):
|
def test_none_name(self):
|
||||||
ops = [migrations.RunSQL('SELECT 1 FROM person;')]
|
class Migration(migrations.Migration):
|
||||||
suggest_name = MigrationAutodetector.suggest_name(ops)
|
operations = [migrations.RunSQL('SELECT 1 FROM person;')]
|
||||||
|
|
||||||
|
migration = Migration('0001_initial', 'test_app')
|
||||||
|
suggest_name = migration.suggest_name()
|
||||||
self.assertIs(suggest_name.startswith('auto_'), True)
|
self.assertIs(suggest_name.startswith('auto_'), True)
|
||||||
|
|
||||||
def test_auto(self):
|
def test_auto(self):
|
||||||
suggest_name = MigrationAutodetector.suggest_name([])
|
migration = migrations.Migration('0001_initial', 'test_app')
|
||||||
|
suggest_name = migration.suggest_name()
|
||||||
self.assertIs(suggest_name.startswith('auto_'), True)
|
self.assertIs(suggest_name.startswith('auto_'), True)
|
||||||
|
|
Loading…
Reference in New Issue