diff --git a/django/apps/registry.py b/django/apps/registry.py index 96d4db5f17..0602c4ff57 100644 --- a/django/apps/registry.py +++ b/django/apps/registry.py @@ -147,7 +147,12 @@ class Apps(object): try: return self.app_configs[app_label] except KeyError: - raise LookupError("No installed app with label '%s'." % app_label) + message = "No installed app with label '%s'." % app_label + for app_config in self.get_app_configs(): + if app_config.name == app_label: + message += " Did you mean '%s'?" % app_config.label + break + raise LookupError(message) # This method is performance-critical at least for Django's test suite. @lru_cache.lru_cache(maxsize=None) diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index da1584d561..01b229ce36 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -68,8 +68,8 @@ class Command(BaseCommand): else: try: app_config = apps.get_app_config(exclude) - except LookupError: - raise CommandError('Unknown app in excludes: %s' % exclude) + except LookupError as e: + raise CommandError(str(e)) excluded_apps.add(app_config) if len(app_labels) == 0: @@ -87,8 +87,8 @@ class Command(BaseCommand): app_label, model_label = label.split('.') try: app_config = apps.get_app_config(app_label) - except LookupError: - raise CommandError("Unknown application: %s" % app_label) + except LookupError as e: + raise CommandError(str(e)) if app_config.models_module is None or app_config in excluded_apps: continue try: @@ -111,8 +111,8 @@ class Command(BaseCommand): app_label = label try: app_config = apps.get_app_config(app_label) - except LookupError: - raise CommandError("Unknown application: %s" % app_label) + except LookupError as e: + raise CommandError(str(e)) if app_config.models_module is None or app_config in excluded_apps: continue app_list[app_config] = None diff --git a/tests/apps/tests.py b/tests/apps/tests.py index e7e5c53534..2837e78aff 100644 --- a/tests/apps/tests.py +++ b/tests/apps/tests.py @@ -121,6 +121,10 @@ class AppsTests(SimpleTestCase): with self.assertRaises(LookupError): apps.get_app_config('webdesign') + msg = "No installed app with label 'django.contrib.auth'. Did you mean 'myauth'" + with self.assertRaisesMessage(LookupError, msg): + apps.get_app_config('django.contrib.auth') + @override_settings(INSTALLED_APPS=SOME_INSTALLED_APPS) def test_is_installed(self): """ diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index 8f2e560781..544b70473b 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -216,7 +216,7 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): # Excluding a bogus app should throw an error with six.assertRaisesRegex(self, management.CommandError, - "Unknown app in excludes: foo_app"): + "No installed app with label 'foo_app'."): self._dumpdata_assert(['fixtures', 'sites'], '', exclude_list=['foo_app']) # Excluding a bogus model should throw an error