diff --git a/django/apps/config.py b/django/apps/config.py index 8c276d5d34..928e19ac44 100644 --- a/django/apps/config.py +++ b/django/apps/config.py @@ -89,6 +89,7 @@ class AppConfig: """ # create() eventually returns app_config_class(app_name, app_module). app_config_class = None + app_config_name = None app_name = None app_module = None @@ -161,12 +162,15 @@ class AppConfig: ) else: message += ( - "However, Django's automatic detection picked another " - "configuration, %r. You should move the default " - "config class to the apps submodule of your " - "application and, if this module defines several " - "config classes, mark the default one with default = " - "True." % app_config_name + "However, Django's automatic detection %s. You should " + "move the default config class to the apps submodule " + "of your application and, if this module defines " + "several config classes, mark the default one with " + "default = True." % ( + "picked another configuration, %r" % app_config_name + if app_config_name + else "did not find this configuration" + ) ) warnings.warn(message, RemovedInDjango41Warning, stacklevel=2) entry = new_entry diff --git a/tests/apps/explicit_default_config_empty_apps/__init__.py b/tests/apps/explicit_default_config_empty_apps/__init__.py new file mode 100644 index 0000000000..a7a4f548d7 --- /dev/null +++ b/tests/apps/explicit_default_config_empty_apps/__init__.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +default_app_config = 'apps.explicit_default_config_empty_apps.ExplicitDefaultConfigEmptyApps' + + +class ExplicitDefaultConfigEmptyApps(AppConfig): + name = 'apps.explicit_default_config_empty_apps' diff --git a/tests/apps/explicit_default_config_empty_apps/apps.py b/tests/apps/explicit_default_config_empty_apps/apps.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/apps/explicit_default_config_without_apps/__init__.py b/tests/apps/explicit_default_config_without_apps/__init__.py new file mode 100644 index 0000000000..c42323376f --- /dev/null +++ b/tests/apps/explicit_default_config_without_apps/__init__.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + +default_app_config = 'apps.explicit_default_config_without_apps.ExplicitDefaultConfigWithoutApps' + + +class ExplicitDefaultConfigWithoutApps(AppConfig): + name = 'apps.explicit_default_config_without_apps' diff --git a/tests/apps/tests.py b/tests/apps/tests.py index f4b0a8879b..cf487a65da 100644 --- a/tests/apps/tests.py +++ b/tests/apps/tests.py @@ -10,9 +10,13 @@ from django.test.utils import extend_sys_path, isolate_apps from django.utils.deprecation import RemovedInDjango41Warning from .explicit_default_config_app.apps import ExplicitDefaultConfig +from .explicit_default_config_empty_apps import ExplicitDefaultConfigEmptyApps from .explicit_default_config_mismatch_app.not_apps import ( ExplicitDefaultConfigMismatch, ) +from .explicit_default_config_without_apps import ( + ExplicitDefaultConfigWithoutApps, +) from .models import SoAlternative, TotallyNormal, new_apps from .one_config_app.apps import OneConfig from .two_configs_one_default_app.apps import TwoConfig @@ -520,3 +524,51 @@ class DeprecationTests(SimpleTestCase): with self.settings(INSTALLED_APPS=['apps.explicit_default_config_mismatch_app']): config = apps.get_app_config('explicit_default_config_mismatch_app') self.assertIsInstance(config, ExplicitDefaultConfigMismatch) + + def test_explicit_default_app_config_empty_apps(self): + """ + Load an app that specifies a default AppConfig class in __init__ and + have an empty apps module. + """ + msg = ( + "'apps.explicit_default_config_empty_apps' defines " + "default_app_config = 'apps.explicit_default_config_empty_apps." + "ExplicitDefaultConfigEmptyApps'. However, Django's automatic " + "detection did not find this configuration. You should move the " + "default config class to the apps submodule of your application " + "and, if this module defines several config classes, mark the " + "default one with default = True." + ) + with self.assertRaisesMessage(RemovedInDjango41Warning, msg): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_empty_apps']): + pass + with ignore_warnings(category=RemovedInDjango41Warning): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_empty_apps']): + self.assertIsInstance( + apps.get_app_config('explicit_default_config_empty_apps'), + ExplicitDefaultConfigEmptyApps, + ) + + def test_explicit_default_app_config_without_apps(self): + """ + Load an app that specifies a default AppConfig class in __init__ and do + not have an apps module. + """ + msg = ( + "'apps.explicit_default_config_without_apps' defines " + "default_app_config = 'apps.explicit_default_config_without_apps." + "ExplicitDefaultConfigWithoutApps'. However, Django's automatic " + "detection did not find this configuration. You should move the " + "default config class to the apps submodule of your application " + "and, if this module defines several config classes, mark the " + "default one with default = True." + ) + with self.assertRaisesMessage(RemovedInDjango41Warning, msg): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_without_apps']): + pass + with ignore_warnings(category=RemovedInDjango41Warning): + with self.settings(INSTALLED_APPS=['apps.explicit_default_config_without_apps']): + self.assertIsInstance( + apps.get_app_config('explicit_default_config_without_apps'), + ExplicitDefaultConfigWithoutApps, + )