diff --git a/debug_toolbar/apps.py b/debug_toolbar/apps.py index de469f190..2848e72d5 100644 --- a/debug_toolbar/apps.py +++ b/debug_toolbar/apps.py @@ -22,6 +22,24 @@ def ready(self): DebugToolbar.get_panel_classes() +def check_template_config(config): + """ + Checks if a template configuration is valid. + + The toolbar requires either the toolbars to be unspecified or + ``django.template.loaders.app_directories.Loader`` to be + included in the loaders. + If custom loaders are specified, then APP_DIRS must be True. + """ + app_dirs = config.get("APP_DIRS", False) + loaders = config.get("OPTIONS", {}).get("loaders", None) + # By default the app loader is included. + has_app_loaders = ( + loaders is None or "django.template.loaders.app_directories.Loader" in loaders + ) + return has_app_loaders or app_dirs + + @register def check_middleware(app_configs, **kwargs): from debug_toolbar.middleware import DebugToolbarMiddleware @@ -30,13 +48,16 @@ def check_middleware(app_configs, **kwargs): gzip_index = None debug_toolbar_indexes = [] - if all(not config.get("APP_DIRS", False) for config in settings.TEMPLATES): + if all(not check_template_config(config) for config in settings.TEMPLATES): errors.append( Warning( "At least one DjangoTemplates TEMPLATES configuration needs " - "to have APP_DIRS set to True.", + "to use django.template.loaders.app_directories.Loader or " + "have APP_DIRS set to True.", hint=( - "Use APP_DIRS=True for at least one " + "Include django.template.loaders.app_directories.Loader " + 'in ["OPTIONS"]["loaders"]. Alternatively use ' + "APP_DIRS=True for at least one " "django.template.backends.django.DjangoTemplates " "backend configuration." ), diff --git a/docs/changes.rst b/docs/changes.rst index a24be5ce7..76c839252 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -5,6 +5,8 @@ Next version ------------ * Removed support for Django < 3.2. +* Updated check ``W006`` to look for + ``django.template.loaders.app_directories.Loader``. 3.2.4 (2021-12-15) ------------------ diff --git a/docs/checks.rst b/docs/checks.rst index 4d4882db6..1140d6b49 100644 --- a/docs/checks.rst +++ b/docs/checks.rst @@ -15,4 +15,6 @@ Debug Toolbar setup and configuration: ``MIDDLEWARE_CLASSES`` setting. * **debug_toolbar.W005**: Setting ``DEBUG_TOOLBAR_PANELS`` is empty. * **debug_toolbar.W006**: At least one ``DjangoTemplates`` ``TEMPLATES`` - configuration needs to have ``APP_DIRS`` set to ``True``. + configuration needs to have + ``django.template.loaders.app_directories.Loader`` included in + ``["OPTIONS"]["loaders"]`` or ``APP_DIRS`` set to ``True``. diff --git a/tests/test_checks.py b/tests/test_checks.py index 15464f9a2..1e24688da 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -134,21 +134,27 @@ def test_panels_is_empty(self): "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", - ] + ], + "loaders": [ + "django.template.loaders.filesystem.Loader", + ], }, }, ] ) - def test_templates_is_using_app_dirs_false(self): + def test_check_w006_invalid(self): errors = run_checks() self.assertEqual( errors, [ Warning( - "At least one DjangoTemplates TEMPLATES configuration " - "needs to have APP_DIRS set to True.", + "At least one DjangoTemplates TEMPLATES configuration needs " + "to use django.template.loaders.app_directories.Loader or " + "have APP_DIRS set to True.", hint=( - "Use APP_DIRS=True for at least one " + "Include django.template.loaders.app_directories.Loader " + 'in ["OPTIONS"]["loaders"]. Alternatively use ' + "APP_DIRS=True for at least one " "django.template.backends.django.DjangoTemplates " "backend configuration." ), @@ -156,3 +162,39 @@ def test_templates_is_using_app_dirs_false(self): ) ], ) + + @override_settings( + TEMPLATES=[ + { + "NAME": "use_loaders", + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": False, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + "loaders": [ + "django.template.loaders.app_directories.Loader", + ], + }, + }, + { + "NAME": "use_app_dirs", + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, + ] + ) + def test_check_w006_valid(self): + self.assertEqual(run_checks(), [])