summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2021-08-06 09:17:13 -0400
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-10-12 15:19:39 +0200
commit32f1fe5f89bc9ae98161c07f3676f6aaedc8e877 (patch)
treecea3542a8fac71cd0e3a2c43e01b0c42362a7e39
parent241ba23870221085cc31ae302b9647f375f9c6c6 (diff)
Fixed #29470 -- Logged makemigrations automatic decisions in non-interactive mode.
-rw-r--r--django/core/management/commands/makemigrations.py7
-rw-r--r--django/db/migrations/questioner.py32
-rw-r--r--docs/releases/4.1.txt3
-rw-r--r--tests/migrations/test_commands.py26
4 files changed, 62 insertions, 6 deletions
diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py
index d8eef481bd..9077660467 100644
--- a/django/core/management/commands/makemigrations.py
+++ b/django/core/management/commands/makemigrations.py
@@ -146,7 +146,12 @@ class Command(BaseCommand):
if self.interactive:
questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run)
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
autodetector = MigrationAutodetector(
loader.project_state(),
diff --git a/django/db/migrations/questioner.py b/django/db/migrations/questioner.py
index 9284e6be41..17883ca76c 100644
--- a/django/db/migrations/questioner.py
+++ b/django/db/migrations/questioner.py
@@ -258,15 +258,47 @@ class InteractiveMigrationQuestioner(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):
# 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)
def ask_not_null_alteration(self, field_name, model_name):
# 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
def ask_auto_now_add_addition(self, field_name, model_name):
# 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)
diff --git a/docs/releases/4.1.txt b/docs/releases/4.1.txt
index e74e3e07f1..af4b6d83a3 100644
--- a/docs/releases/4.1.txt
+++ b/docs/releases/4.1.txt
@@ -163,7 +163,8 @@ Logging
Management Commands
~~~~~~~~~~~~~~~~~~~
-* ...
+* :option:`makemigrations --no-input` now logs default answers and reasons why
+ migrations cannot be created.
Migrations
~~~~~~~~~~
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 3e76332630..7b173c68bc 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -1361,7 +1361,14 @@ class MakeMigrationsTests(MigrationTestBase):
with self.assertRaises(SystemExit):
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):
"""
@@ -1417,10 +1424,15 @@ class MakeMigrationsTests(MigrationTestBase):
class Meta:
app_label = "migrations"
- out = io.StringIO()
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(
+ "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):
"""
@@ -1884,8 +1896,14 @@ class MakeMigrationsTests(MigrationTestBase):
app_label = 'migrations'
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)
+ 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):
"""