diff --git a/django/core/checks/__init__.py b/django/core/checks/__init__.py index efeddd1bdf..b96b5ba4e4 100644 --- a/django/core/checks/__init__.py +++ b/django/core/checks/__init__.py @@ -11,6 +11,7 @@ import django.core.checks.model_checks # NOQA import django.core.checks.security.base # NOQA import django.core.checks.security.csrf # NOQA import django.core.checks.security.sessions # NOQA +import django.core.checks.templates # NOQA __all__ = [ 'CheckMessage', diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py index 88cc519a50..98476bb917 100644 --- a/django/core/checks/registry.py +++ b/django/core/checks/registry.py @@ -15,6 +15,7 @@ class Tags(object): models = 'models' security = 'security' signals = 'signals' + templates = 'templates' class CheckRegistry(object): diff --git a/django/core/checks/templates.py b/django/core/checks/templates.py new file mode 100644 index 0000000000..ef1e0a6306 --- /dev/null +++ b/django/core/checks/templates.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf import settings + +from . import Error, Tags, register + +E001 = Error( + "You have 'APP_DIRS': True in your TEMPLATES but also specify 'loaders' " + "in OPTIONS. Either remove APP_DIRS or remove the 'loaders' option.", + id='templates.E001', +) + + +@register(Tags.templates) +def check_setting_app_dirs_loaders(app_configs, **kwargs): + passed_check = True + for conf in settings.TEMPLATES: + if not conf.get('APP_DIRS'): + continue + if 'loaders' in conf.get('OPTIONS', {}): + passed_check = False + return [] if passed_check else [E001] diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index eb6fa688a2..d536560f0a 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -491,3 +491,13 @@ If you're using MySQL, the following checks will be performed: * **mysql.E001**: MySQL does not allow unique ``CharField``\s to have a ``max_length`` > 255. + +Templates +--------- + +The following checks verify that your :setting:`TEMPLATES` setting is correctly +configured: + +* **templates.E001**: You have ``'APP_DIRS': True`` in your + :setting:`TEMPLATES` but also specify ``'loaders'`` in ``OPTIONS``. Either + remove ``APP_DIRS`` or remove the ``'loaders'`` option. diff --git a/tests/check_framework/test_templates.py b/tests/check_framework/test_templates.py new file mode 100644 index 0000000000..27ccf138a7 --- /dev/null +++ b/tests/check_framework/test_templates.py @@ -0,0 +1,39 @@ +from django.core.checks.templates import E001 +from django.test import SimpleTestCase +from django.test.utils import override_settings + + +class CheckTemplateSettingsAppDirsTest(SimpleTestCase): + TEMPLATES_APP_DIRS_AND_LOADERS = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'APP_DIRS': True, + 'OPTIONS': { + 'loaders': ['django.template.loaders.filesystem.Loader'], + }, + }, + ] + + @property + def func(self): + from django.core.checks.templates import check_setting_app_dirs_loaders + return check_setting_app_dirs_loaders + + @override_settings(TEMPLATES=TEMPLATES_APP_DIRS_AND_LOADERS) + def test_app_dirs_and_loaders(self): + """ + Error if template loaders are specified and APP_DIRS is True. + """ + self.assertEqual(self.func(None), [E001]) + + def test_app_dirs_removed(self): + TEMPLATES = self.TEMPLATES_APP_DIRS_AND_LOADERS[:] + del TEMPLATES[0]['APP_DIRS'] + with self.settings(TEMPLATES=TEMPLATES): + self.assertEqual(self.func(None), []) + + def test_loaders_removed(self): + TEMPLATES = self.TEMPLATES_APP_DIRS_AND_LOADERS[:] + del TEMPLATES[0]['OPTIONS']['loaders'] + with self.settings(TEMPLATES=TEMPLATES): + self.assertEqual(self.func(None), [])