Fixed #29470 -- Logged makemigrations automatic decisions in non-interactive mode.
This commit is contained in:
parent
241ba23870
commit
32f1fe5f89
|
@ -146,7 +146,12 @@ class Command(BaseCommand):
|
||||||
if self.interactive:
|
if self.interactive:
|
||||||
questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
|
questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
|
||||||
else:
|
else:
|
||||||
questioner = NonInteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
|
questioner = NonInteractiveMigrationQuestioner(
|
||||||
|
specified_apps=app_labels,
|
||||||
|
dry_run=self.dry_run,
|
||||||
|
verbosity=self.verbosity,
|
||||||
|
log=self.log,
|
||||||
|
)
|
||||||
# Set up autodetector
|
# Set up autodetector
|
||||||
autodetector = MigrationAutodetector(
|
autodetector = MigrationAutodetector(
|
||||||
loader.project_state(),
|
loader.project_state(),
|
||||||
|
|
|
@ -258,15 +258,47 @@ class InteractiveMigrationQuestioner(MigrationQuestioner):
|
||||||
|
|
||||||
|
|
||||||
class NonInteractiveMigrationQuestioner(MigrationQuestioner):
|
class NonInteractiveMigrationQuestioner(MigrationQuestioner):
|
||||||
|
def __init__(
|
||||||
|
self, defaults=None, specified_apps=None, dry_run=None, verbosity=1,
|
||||||
|
log=None,
|
||||||
|
):
|
||||||
|
self.verbosity = verbosity
|
||||||
|
self.log = log
|
||||||
|
super().__init__(
|
||||||
|
defaults=defaults, specified_apps=specified_apps, dry_run=dry_run,
|
||||||
|
)
|
||||||
|
|
||||||
|
def log_lack_of_migration(self, field_name, model_name, reason):
|
||||||
|
if self.verbosity > 0:
|
||||||
|
self.log(
|
||||||
|
f"Field '{field_name}' on model '{model_name}' not migrated: "
|
||||||
|
f"{reason}."
|
||||||
|
)
|
||||||
|
|
||||||
def ask_not_null_addition(self, field_name, model_name):
|
def ask_not_null_addition(self, field_name, model_name):
|
||||||
# We can't ask the user, so act like the user aborted.
|
# We can't ask the user, so act like the user aborted.
|
||||||
|
self.log_lack_of_migration(
|
||||||
|
field_name,
|
||||||
|
model_name,
|
||||||
|
'it is impossible to add a non-nullable field without specifying '
|
||||||
|
'a default',
|
||||||
|
)
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
def ask_not_null_alteration(self, field_name, model_name):
|
def ask_not_null_alteration(self, field_name, model_name):
|
||||||
# We can't ask the user, so set as not provided.
|
# We can't ask the user, so set as not provided.
|
||||||
|
self.log(
|
||||||
|
f"Field '{field_name}' on model '{model_name}' given a default of "
|
||||||
|
f"NOT PROVIDED and must be corrected."
|
||||||
|
)
|
||||||
return NOT_PROVIDED
|
return NOT_PROVIDED
|
||||||
|
|
||||||
def ask_auto_now_add_addition(self, field_name, model_name):
|
def ask_auto_now_add_addition(self, field_name, model_name):
|
||||||
# We can't ask the user, so act like the user aborted.
|
# We can't ask the user, so act like the user aborted.
|
||||||
|
self.log_lack_of_migration(
|
||||||
|
field_name,
|
||||||
|
model_name,
|
||||||
|
"it is impossible to add a field with 'auto_now_add=True' without "
|
||||||
|
"specifying a default",
|
||||||
|
)
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
|
@ -163,7 +163,8 @@ Logging
|
||||||
Management Commands
|
Management Commands
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* :option:`makemigrations --no-input` now logs default answers and reasons why
|
||||||
|
migrations cannot be created.
|
||||||
|
|
||||||
Migrations
|
Migrations
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
|
@ -1361,7 +1361,14 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
|
|
||||||
with self.assertRaises(SystemExit):
|
with self.assertRaises(SystemExit):
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
with self.temporary_migration_module(module="migrations.test_migrations_no_default"):
|
||||||
call_command("makemigrations", "migrations", interactive=False)
|
with captured_stdout() as out:
|
||||||
|
call_command('makemigrations', 'migrations', interactive=False)
|
||||||
|
self.assertIn(
|
||||||
|
"Field 'silly_int' on model 'sillymodel' not migrated: it is "
|
||||||
|
"impossible to add a non-nullable field without specifying a "
|
||||||
|
"default.",
|
||||||
|
out.getvalue(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_makemigrations_interactive_not_null_addition(self):
|
def test_makemigrations_interactive_not_null_addition(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1417,10 +1424,15 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
class Meta:
|
class Meta:
|
||||||
app_label = "migrations"
|
app_label = "migrations"
|
||||||
|
|
||||||
out = io.StringIO()
|
|
||||||
with self.temporary_migration_module(module="migrations.test_migrations"):
|
with self.temporary_migration_module(module="migrations.test_migrations"):
|
||||||
call_command("makemigrations", "migrations", interactive=False, stdout=out)
|
with captured_stdout() as out:
|
||||||
|
call_command('makemigrations', 'migrations', interactive=False)
|
||||||
self.assertIn("Alter field slug on author", out.getvalue())
|
self.assertIn("Alter field slug on author", out.getvalue())
|
||||||
|
self.assertIn(
|
||||||
|
"Field 'slug' on model 'author' given a default of NOT PROVIDED "
|
||||||
|
"and must be corrected.",
|
||||||
|
out.getvalue(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_makemigrations_interactive_not_null_alteration(self):
|
def test_makemigrations_interactive_not_null_alteration(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1884,8 +1896,14 @@ class MakeMigrationsTests(MigrationTestBase):
|
||||||
app_label = 'migrations'
|
app_label = 'migrations'
|
||||||
|
|
||||||
with self.temporary_migration_module(module='migrations.test_auto_now_add'):
|
with self.temporary_migration_module(module='migrations.test_auto_now_add'):
|
||||||
with self.assertRaises(SystemExit):
|
with self.assertRaises(SystemExit), captured_stdout() as out:
|
||||||
call_command('makemigrations', 'migrations', interactive=False)
|
call_command('makemigrations', 'migrations', interactive=False)
|
||||||
|
self.assertIn(
|
||||||
|
"Field 'creation_date' on model 'entry' not migrated: it is "
|
||||||
|
"impossible to add a field with 'auto_now_add=True' without "
|
||||||
|
"specifying a default.",
|
||||||
|
out.getvalue(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_makemigrations_interactive_unique_callable_default_addition(self):
|
def test_makemigrations_interactive_unique_callable_default_addition(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue