Repository: django-extensions/django-extensions

Issue:
validate_templates isn't valid when migrated to the 1.8 TEMPLATES setting.
`TEMPLATE_DIRS` is deprecated in favor of `TEMPLATES['DIRS']`. If the setting doesn't exist this will fail:

https://github.com/django-extensions/django-extensions/blob/master/django_extensions/management/commands/validate_templates.py#L54



Discussion:

Resolving patch:
diff --git a/django_extensions/compat.py b/django_extensions/compat.py
--- a/django_extensions/compat.py
+++ b/django_extensions/compat.py
@@ -4,6 +4,8 @@
 import importlib
 import django
 
+from django.conf import settings
+
 
 #
 # Django compatibility
@@ -38,3 +40,15 @@ def add_to_builtins_compat(name):
     else:
         from django.template import engines
         engines['django'].engine.builtins.append(name)
+
+
+def get_template_setting(template_key, default=None):
+    """ Read template settings pre and post django 1.8 """
+    templates_var = getattr(settings, 'TEMPLATES', None)
+    if templates_var is not None and template_key in templates_var[0]:
+        return templates_var[0][template_key]
+    if template_key == 'DIRS':
+        pre18_template_key = 'TEMPLATES_%s' % template_key
+        value = getattr(settings, pre18_template_key, default)
+        return value
+    return default
diff --git a/django_extensions/management/commands/notes.py b/django_extensions/management/commands/notes.py
--- a/django_extensions/management/commands/notes.py
+++ b/django_extensions/management/commands/notes.py
@@ -7,6 +7,7 @@
 from django.conf import settings
 from django.core.management.base import BaseCommand
 
+from django_extensions.compat import get_template_setting
 from django_extensions.management.utils import signalcommand
 
 ANNOTATION_RE = re.compile("\{?#[\s]*?(TODO|FIXME|BUG|HACK|WARNING|NOTE|XXX)[\s:]?(.+)")
@@ -22,7 +23,7 @@ class Command(BaseCommand):
     def handle(self, *args, **options):
         # don't add django internal code
         apps = [app for app in filter(lambda app: not app.startswith('django.contrib'), settings.INSTALLED_APPS)]
-        template_dirs = getattr(settings, 'TEMPLATE_DIRS', [])
+        template_dirs = get_template_setting('DIRS', [])
         if template_dirs:
             apps += template_dirs
         for app_dir in apps:
diff --git a/django_extensions/management/commands/validate_templates.py b/django_extensions/management/commands/validate_templates.py
--- a/django_extensions/management/commands/validate_templates.py
+++ b/django_extensions/management/commands/validate_templates.py
@@ -5,7 +5,7 @@
 from django.core.management.color import color_style
 from django.template.loader import get_template
 
-from django_extensions.compat import add_to_builtins_compat
+from django_extensions.compat import add_to_builtins_compat, get_template_setting
 from django_extensions.management.utils import signalcommand
 from django_extensions.utils import validatingtemplatetags
 
@@ -35,23 +35,22 @@ def add_arguments(self, parser):
             "(without {%% load urls from future %%}")
         parser.add_argument(
             '--include', '-i', action='append', dest='includes',
-            default=[], help="Append these paths to TEMPLATE_DIRS")
+            default=[], help="Append these paths to TEMPLATE DIRS")
 
     @signalcommand
     def handle(self, *args, **options):
         from django.conf import settings
         style = color_style()
-        template_dirs = set(settings.TEMPLATE_DIRS)
+        template_dirs = set(get_template_setting('DIRS'))
         template_dirs |= set(options.get('includes', []))
         template_dirs |= set(getattr(settings, 'VALIDATE_TEMPLATES_EXTRA_TEMPLATE_DIRS', []))
 
-        # Load in Templates from 1.8
+        # This is unsafe:
+        # https://docs.djangoproject.com/en/1.10/topics/settings/#altering-settings-at-runtime
         if hasattr(settings, 'TEMPLATES'):
-            for template_engine in settings.TEMPLATES:
-                if 'DIRS' in template_engine:
-                    template_dirs |= set(template_engine['DIRS'])
-
-        settings.TEMPLATE_DIRS = list(template_dirs)
+            settings.TEMPLATES[0]['DIRS'] = list(template_dirs)
+        else:
+            settings.TEMPLATE_DIRS = list(template_dirs)
         settings.TEMPLATE_DEBUG = True
         verbosity = int(options.get('verbosity', 1))
         errors = 0
@@ -73,7 +72,7 @@ def handle(self, *args, **options):
                         print(filepath)
                     validatingtemplatetags.before_new_template(options.get('force_new_urls', False))
                     try:
-                        get_template(filename, [root])
+                        get_template(filepath)
                     except Exception as e:
                         errors += 1
                         print("%s: %s" % (filepath, style.ERROR("%s %s" % (e.__class__.__name__, str(e)))))


Test patch:
diff --git a/tests/test_compat.py b/tests/test_compat.py
new file mode 100644
--- /dev/null
+++ b/tests/test_compat.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+from django.test import TestCase, override_settings
+
+from django_extensions.compat import get_template_setting
+
+
+class GetTemplateSettingTests(TestCase):
+    @override_settings(TEMPLATES=[{'DIRS': ['asdf']}])
+    def test_new_dir_template(self):
+        setting = get_template_setting('DIRS')
+        self.assertEqual(setting, ['asdf'])
+
+    @override_settings(TEMPLATES=None, TEMPLATES_DIRS=['asdf'])
+    def test_old_dir_template(self):
+        setting = get_template_setting('DIRS')
+        self.assertEqual(setting, ['asdf'])
+
+    @override_settings(TEMPLATES=None)
+    def test_old_dir_missing(self):
+        setting = get_template_setting('DIRS', 'default')
+        self.assertEqual(setting, 'default')
+
+    def test_default_setting(self):
+        setting = get_template_setting('ASDF', 'default')
+        self.assertEqual(setting, 'default')