diff --git a/django/core/management/commands/squashmigrations.py b/django/core/management/commands/squashmigrations.py index 68c2a4ea5d..9be6750aed 100644 --- a/django/core/management/commands/squashmigrations.py +++ b/django/core/management/commands/squashmigrations.py @@ -1,3 +1,4 @@ +from django.apps import apps from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django.db import DEFAULT_DB_ALIAS, connections, migrations @@ -46,7 +47,11 @@ class Command(BaseCommand): migration_name = options['migration_name'] no_optimize = options['no_optimize'] squashed_name = options['squashed_name'] - + # Validate app_label. + try: + apps.get_app_config(app_label) + except LookupError as err: + raise CommandError(str(err)) # Load the current graph state, check the app and migration they asked for exists loader = MigrationLoader(connections[DEFAULT_DB_ALIAS]) if app_label not in loader.migrated_apps: diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 494d5cd211..4f01a3b665 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -1433,3 +1433,11 @@ class AppLabelErrorTests(TestCase): def test_migrate_app_name_specified_as_label(self): with self.assertRaisesMessage(CommandError, self.did_you_mean_auth_error): call_command('migrate', 'django.contrib.auth') + + def test_squashmigrations_nonexistent_app_label(self): + with self.assertRaisesMessage(CommandError, self.nonexistent_app_error): + call_command('squashmigrations', 'nonexistent_app', '0002') + + def test_squashmigrations_app_name_specified_as_label(self): + with self.assertRaisesMessage(CommandError, self.did_you_mean_auth_error): + call_command('squashmigrations', 'django.contrib.auth', '0002')