diff --git a/django/core/management/commands/makemigrations.py b/django/core/management/commands/makemigrations.py index 14461418c1..1a166c6f99 100644 --- a/django/core/management/commands/makemigrations.py +++ b/django/core/management/commands/makemigrations.py @@ -73,7 +73,15 @@ class Command(BaseCommand): bad_app_labels.add(app_label) if bad_app_labels: for app_label in bad_app_labels: - self.stderr.write("App '%s' could not be found. Is it in INSTALLED_APPS?" % app_label) + if '.' in app_label: + self.stderr.write( + "'%s' is not a valid app label. Did you mean '%s'?" % ( + app_label, + app_label.split('.')[-1], + ) + ) + else: + self.stderr.write("App '%s' could not be found. Is it in INSTALLED_APPS?" % app_label) sys.exit(2) # Load the current graph state. Pass in None for the connection so diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 933c00eada..76b8e39b17 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -786,6 +786,12 @@ class MakeMigrationsTests(MigrationTestBase): call_command("makemigrations", "this_app_does_not_exist", stderr=err) self.assertIn("'this_app_does_not_exist' could not be found.", err.getvalue()) + def test_makemigrations_app_name_with_dots(self): + err = io.StringIO() + with self.assertRaises(SystemExit): + call_command('makemigrations', 'invalid.app.label', stderr=err) + self.assertIn("'invalid.app.label' is not a valid app label. Did you mean 'label'?", err.getvalue()) + def test_makemigrations_empty_no_app_specified(self): """ makemigrations exits if no app is specified with 'empty' mode.