ソースを参照

Fixed #29470 -- Logged makemigrations automatic decisions in non-interactive mode.

Jacob Walls 3 年 前
コミット
32f1fe5f89

+ 6 - 1
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(),

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

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

+ 22 - 4
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):
         """