Browse Source

Deprecated TEMPLATE_DIRS.

Aymeric Augustin 10 years ago
parent
commit
d3205e3e2e

+ 12 - 0
django/contrib/flatpages/tests/settings.py

@@ -0,0 +1,12 @@
+import os
+
+
+FLATPAGES_TEMPLATES = [{
+    'BACKEND': 'django.template.backends.django.DjangoTemplates',
+    'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')],
+    'OPTIONS': {
+        'context_processors': (
+            'django.contrib.auth.context_processors.auth',
+        ),
+    },
+}]

+ 3 - 4
django/contrib/flatpages/tests/test_csrf.py

@@ -1,9 +1,10 @@
-import os
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.test import TestCase, Client
 from django.test import TestCase, Client
 from django.test import override_settings
 from django.test import override_settings
 
 
+from .settings import FLATPAGES_TEMPLATES
+
 
 
 @override_settings(
 @override_settings(
     LOGIN_URL='/accounts/login/',
     LOGIN_URL='/accounts/login/',
@@ -17,9 +18,7 @@ from django.test import override_settings
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     CSRF_FAILURE_VIEW='django.views.csrf.csrf_failure',
     CSRF_FAILURE_VIEW='django.views.csrf.csrf_failure',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageCSRFTests(TestCase):
 class FlatpageCSRFTests(TestCase):

+ 4 - 7
django/contrib/flatpages/tests/test_middleware.py

@@ -1,10 +1,11 @@
-import os
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.flatpages.models import FlatPage
 from django.contrib.flatpages.models import FlatPage
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 
 
+from .settings import FLATPAGES_TEMPLATES
+
 
 
 @override_settings(
 @override_settings(
     LOGIN_URL='/accounts/login/',
     LOGIN_URL='/accounts/login/',
@@ -17,9 +18,7 @@ from django.test import TestCase, override_settings
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageMiddlewareTests(TestCase):
 class FlatpageMiddlewareTests(TestCase):
@@ -97,9 +96,7 @@ class FlatpageMiddlewareTests(TestCase):
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageMiddlewareAppendSlashTests(TestCase):
 class FlatpageMiddlewareAppendSlashTests(TestCase):

+ 3 - 4
django/contrib/flatpages/tests/test_templatetags.py

@@ -1,9 +1,10 @@
-import os
 from django.contrib.auth.models import AnonymousUser, User
 from django.contrib.auth.models import AnonymousUser, User
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.template import Template, Context, TemplateSyntaxError
 from django.template import Template, Context, TemplateSyntaxError
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 
 
+from .settings import FLATPAGES_TEMPLATES
+
 
 
 @override_settings(
 @override_settings(
     MIDDLEWARE_CLASSES=(
     MIDDLEWARE_CLASSES=(
@@ -15,9 +16,7 @@ from django.test import TestCase, override_settings
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
         'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageTemplateTagTests(TestCase):
 class FlatpageTemplateTagTests(TestCase):

+ 4 - 7
django/contrib/flatpages/tests/test_views.py

@@ -1,10 +1,11 @@
-import os
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.auth.tests.utils import skipIfCustomUser
 from django.contrib.flatpages.models import FlatPage
 from django.contrib.flatpages.models import FlatPage
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 
 
+from .settings import FLATPAGES_TEMPLATES
+
 
 
 @override_settings(
 @override_settings(
     LOGIN_URL='/accounts/login/',
     LOGIN_URL='/accounts/login/',
@@ -17,9 +18,7 @@ from django.test import TestCase, override_settings
         # no 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
         # no 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageViewTests(TestCase):
 class FlatpageViewTests(TestCase):
@@ -85,9 +84,7 @@ class FlatpageViewTests(TestCase):
         # no 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
         # no 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
     ),
     ),
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
     ROOT_URLCONF='django.contrib.flatpages.tests.urls',
-    TEMPLATE_DIRS=(
+    TEMPLATES=FLATPAGES_TEMPLATES,
-        os.path.join(os.path.dirname(__file__), 'templates'),
-    ),
     SITE_ID=1,
     SITE_ID=1,
 )
 )
 class FlatpageViewAppendSlashTests(TestCase):
 class FlatpageViewAppendSlashTests(TestCase):

+ 26 - 6
django/contrib/messages/tests/base.py

@@ -2,7 +2,6 @@ from unittest import skipUnless
 
 
 from django import http
 from django import http
 from django.apps import apps
 from django.apps import apps
-from django.conf import global_settings
 from django.contrib.messages import constants, utils, get_level, set_level
 from django.contrib.messages import constants, utils, get_level, set_level
 from django.contrib.messages.api import MessageFailure
 from django.contrib.messages.api import MessageFailure
 from django.contrib.messages.constants import DEFAULT_LEVELS
 from django.contrib.messages.constants import DEFAULT_LEVELS
@@ -58,8 +57,17 @@ class BaseTests(object):
 
 
     def setUp(self):
     def setUp(self):
         self.settings_override = override_settings_tags(
         self.settings_override = override_settings_tags(
-            TEMPLATE_DIRS=(),
+            TEMPLATES=[{
-            TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS,
+                'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'DIRS': [],
+                'APP_DIRS': True,
+                'OPTIONS': {
+                    'context_processors': (
+                        'django.contrib.auth.context_processors.auth',
+                        'django.contrib.messages.context_processors.messages',
+                    ),
+                },
+            }],
             ROOT_URLCONF='django.contrib.messages.tests.urls',
             ROOT_URLCONF='django.contrib.messages.tests.urls',
             MESSAGE_TAGS='',
             MESSAGE_TAGS='',
             MESSAGE_STORAGE='%s.%s' % (self.storage_class.__module__,
             MESSAGE_STORAGE='%s.%s' % (self.storage_class.__module__,
@@ -219,9 +227,15 @@ class BaseTests(object):
     @modify_settings(
     @modify_settings(
         INSTALLED_APPS={'remove': 'django.contrib.messages'},
         INSTALLED_APPS={'remove': 'django.contrib.messages'},
         MIDDLEWARE_CLASSES={'remove': 'django.contrib.messages.middleware.MessageMiddleware'},
         MIDDLEWARE_CLASSES={'remove': 'django.contrib.messages.middleware.MessageMiddleware'},
-        TEMPLATE_CONTEXT_PROCESSORS={'remove': 'django.contrib.messages.context_processors.messages'},
     )
     )
-    @override_settings(MESSAGE_LEVEL=constants.DEBUG)
+    @override_settings(
+        MESSAGE_LEVEL=constants.DEBUG,
+        TEMPLATES=[{
+            'BACKEND': 'django.template.backends.django.DjangoTemplates',
+            'DIRS': [],
+            'APP_DIRS': True,
+        }],
+    )
     def test_middleware_disabled(self):
     def test_middleware_disabled(self):
         """
         """
         Tests that, when the middleware is disabled, an exception is raised
         Tests that, when the middleware is disabled, an exception is raised
@@ -239,7 +253,13 @@ class BaseTests(object):
     @modify_settings(
     @modify_settings(
         INSTALLED_APPS={'remove': 'django.contrib.messages'},
         INSTALLED_APPS={'remove': 'django.contrib.messages'},
         MIDDLEWARE_CLASSES={'remove': 'django.contrib.messages.middleware.MessageMiddleware'},
         MIDDLEWARE_CLASSES={'remove': 'django.contrib.messages.middleware.MessageMiddleware'},
-        TEMPLATE_CONTEXT_PROCESSORS={'remove': 'django.contrib.messages.context_processors.messages'},
+    )
+    @override_settings(
+        TEMPLATES=[{
+            'BACKEND': 'django.template.backends.django.DjangoTemplates',
+            'DIRS': [],
+            'APP_DIRS': True,
+        }],
     )
     )
     def test_middleware_disabled_fail_silently(self):
     def test_middleware_disabled_fail_silently(self):
         """
         """

+ 8 - 6
django/contrib/sitemaps/tests/test_http.py

@@ -39,9 +39,10 @@ class HTTPSitemapTests(SitemapTestsBase):
 """ % self.base_url
 """ % self.base_url
         self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
         self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
 
 
-    @override_settings(
+    @override_settings(TEMPLATES=[{
-        TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates'),)
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    )
+        'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
+    }])
     def test_simple_sitemap_custom_index(self):
     def test_simple_sitemap_custom_index(self):
         "A simple sitemap index can be rendered with a custom template"
         "A simple sitemap index can be rendered with a custom template"
         with warnings.catch_warnings():
         with warnings.catch_warnings():
@@ -81,9 +82,10 @@ class HTTPSitemapTests(SitemapTestsBase):
 """ % (self.base_url, date.today())
 """ % (self.base_url, date.today())
         self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
         self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
 
 
-    @override_settings(
+    @override_settings(TEMPLATES=[{
-        TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates'),)
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    )
+        'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
+    }])
     def test_simple_custom_sitemap(self):
     def test_simple_custom_sitemap(self):
         "A simple sitemap can be rendered with a custom template"
         "A simple sitemap can be rendered with a custom template"
         response = self.client.get('/simple/custom-sitemap.xml')
         response = self.client.get('/simple/custom-sitemap.xml')

+ 1 - 0
docs/internals/deprecation.txt

@@ -90,6 +90,7 @@ details on these changes.
 * The following settings will be removed:
 * The following settings will be removed:
 
 
   * ``ALLOWED_INCLUDE_ROOTS``
   * ``ALLOWED_INCLUDE_ROOTS``
+  * ``TEMPLATE_DIRS``
   * ``TEMPLATE_LOADERS``
   * ``TEMPLATE_LOADERS``
   * ``TEMPLATE_STRING_IF_INVALID``
   * ``TEMPLATE_STRING_IF_INVALID``
 
 

+ 2 - 2
docs/intro/overview.txt

@@ -254,8 +254,8 @@ The code above loads the ``news/year_archive.html`` template.
 
 
 Django has a template search path, which allows you to minimize redundancy among
 Django has a template search path, which allows you to minimize redundancy among
 templates. In your Django settings, you specify a list of directories to check
 templates. In your Django settings, you specify a list of directories to check
-for templates with :setting:`TEMPLATE_DIRS`. If a template doesn't exist in the
+for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template doesn't exist
-first directory, it checks the second, and so on.
+in the first directory, it checks the second, and so on.
 
 
 Let's say the ``news/year_archive.html`` template was found. Here's what that
 Let's say the ``news/year_archive.html`` template was found. Here's what that
 might look like:
 might look like:

+ 27 - 9
docs/intro/tutorial02.txt

@@ -488,15 +488,32 @@ whatever user your server runs.) However, keeping your templates within the
 project is a good convention to follow.
 project is a good convention to follow.
 
 
 Open your settings file (:file:`mysite/settings.py`, remember) and add a
 Open your settings file (:file:`mysite/settings.py`, remember) and add a
-:setting:`TEMPLATE_DIRS` setting:
+:setting:`DIRS <TEMPLATES-DIRS>` option in the :setting:`TEMPLATES` setting:
 
 
 .. snippet::
 .. snippet::
     :filename: mysite/settings.py
     :filename: mysite/settings.py
 
 
-    TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
+    TEMPLATES = [
-
+        {
-:setting:`TEMPLATE_DIRS` is an iterable of filesystem directories to check when
+            'BACKEND': 'django.template.backends.django.DjangoTemplates',
-loading Django templates; it's a search path.
+            'DIRS': [os.path.join(BASE_DIR, 'templates')],
+            'APP_DIRS': True,
+            'OPTIONS': {
+                'context_processors': [
+                    'django.template.context_processors.debug',
+                    'django.template.context_processors.i18n',
+                    'django.template.context_processors.tz',
+                    'django.template.context_processors.media',
+                    'django.template.context_processors.static',
+                    'django.contrib.auth.context_processors.auth',
+                    'django.contrib.messages.context_processors.messages',
+                ],
+            },
+        },
+    ]
+
+:setting:`DIRS <TEMPLATES-DIRS>` is a list of filesystem directories to check
+when loading Django templates; it's a search path.
 
 
 Now create a directory called ``admin`` inside ``templates``, and copy the
 Now create a directory called ``admin`` inside ``templates``, and copy the
 template ``admin/base_site.html`` from within the default Django admin
 template ``admin/base_site.html`` from within the default Django admin
@@ -547,10 +564,11 @@ changes.
 Customizing your *application's* templates
 Customizing your *application's* templates
 ------------------------------------------
 ------------------------------------------
 
 
-Astute readers will ask: But if :setting:`TEMPLATE_DIRS` was empty by default,
+Astute readers will ask: But if :setting:`DIRS <TEMPLATES-DIRS>` was empty by
-how was Django finding the default admin templates? The answer is that, by
+default, how was Django finding the default admin templates? The answer is
-default, Django automatically looks for a ``templates/`` subdirectory within
+that, since :setting:`APP_DIRS <TEMPLATES-APP_DIRS>` is set to ``True``,
-each application package, for use as a fallback (don't forget that
+Django automatically looks for a ``templates/`` subdirectory within each
+application package, for use as a fallback (don't forget that
 ``django.contrib.admin`` is an application).
 ``django.contrib.admin`` is an application).
 
 
 Our poll application is not very complex and doesn't need custom admin
 Our poll application is not very complex and doesn't need custom admin

+ 2 - 2
docs/ref/contrib/sites.txt

@@ -209,8 +209,8 @@ subscribing to LJWorld.com alerts." Same goes for the email's message body.
 
 
 Note that an even more flexible (but more heavyweight) way of doing this would
 Note that an even more flexible (but more heavyweight) way of doing this would
 be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
 be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
-different template directories (:setting:`TEMPLATE_DIRS`), you could simply
+different template directories (:setting:`DIRS <TEMPLATES-DIRS>`), you could
-farm out to the template system like so::
+simply farm out to the template system like so::
 
 
     from django.core.mail import send_mail
     from django.core.mail import send_mail
     from django.template import loader, Context
     from django.template import loader, Context

+ 5 - 0
docs/ref/settings.txt

@@ -2422,6 +2422,11 @@ TEMPLATE_DIRS
 
 
 Default: ``()`` (Empty tuple)
 Default: ``()`` (Empty tuple)
 
 
+.. deprecated:: 1.8
+
+    Set the :setting:`DIRS <TEMPLATES-DIRS>` option of a ``DjangoTemplates``
+    backend instead.
+
 List of locations of the template source files searched by
 List of locations of the template source files searched by
 :class:`django.template.loaders.filesystem.Loader`, in search order.
 :class:`django.template.loaders.filesystem.Loader`, in search order.
 
 

+ 26 - 17
docs/ref/templates/api.txt

@@ -620,21 +620,30 @@ specified as a **template directory**.
 
 
 Django searches for template directories in a number of places, depending on
 Django searches for template directories in a number of places, depending on
 your template-loader settings (see "Loader types" below), but the most basic
 your template-loader settings (see "Loader types" below), but the most basic
-way of specifying template directories is by using the :setting:`TEMPLATE_DIRS`
+way of specifying template directories is by using the :setting:`DIRS
-setting.
+<TEMPLATES-DIRS>` option.
 
 
-The TEMPLATE_DIRS setting
+The DIRS option
-~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~
+
+.. versionchanged:: 1.8
 
 
-Tell Django what your template directories are by using the
+    This value used to be defined by the ``TEMPLATE_DIRS`` setting.
-:setting:`TEMPLATE_DIRS` setting in your settings file. This should be set to a
-list or tuple of strings that contain full paths to your template
-directory(ies). Example::
 
 
-    TEMPLATE_DIRS = (
+Tell Django what your template directories are by using the :setting:`DIRS
-        "/home/html/templates/lawrence.com",
+<TEMPLATES-DIRS>` option in the :setting:`TEMPLATES` setting in your settings
-        "/home/html/templates/default",
+file. This should be set to a list of strings that contain full paths to your
-    )
+template directory(ies). Example::
+
+    TEMPLATES = [
+        {
+            'BACKEND': 'django.template.backends.django.DjangoTemplates',
+            'DIRS': [
+                '/home/html/templates/lawrence.com',
+                '/home/html/templates/default',
+            ],
+        },
+    ]
 
 
 Your templates can go anywhere you want, as long as the directories and
 Your templates can go anywhere you want, as long as the directories and
 templates are readable by the Web server. They can have any extension you want,
 templates are readable by the Web server. They can have any extension you want,
@@ -679,8 +688,8 @@ The Python API
        The ``dirs`` parameter was deprecated.
        The ``dirs`` parameter was deprecated.
 
 
 For example, if you call ``get_template('story_detail.html')`` and have the
 For example, if you call ``get_template('story_detail.html')`` and have the
-above :setting:`TEMPLATE_DIRS` setting, here are the files Django will look for,
+above :setting:`DIRS <TEMPLATES-DIRS>` option, here are the files Django will
-in order:
+look for, in order:
 
 
 * ``/home/html/templates/lawrence.com/story_detail.html``
 * ``/home/html/templates/lawrence.com/story_detail.html``
 * ``/home/html/templates/default/story_detail.html``
 * ``/home/html/templates/default/story_detail.html``
@@ -718,8 +727,8 @@ To load a template that's within a subdirectory, just use a slash, like so::
 
 
     get_template('news/story_detail.html')
     get_template('news/story_detail.html')
 
 
-Using the same :setting:`TEMPLATE_DIRS` setting from above, this example
+Using the same :setting:`DIRS <TEMPLATES-DIRS>` option from above, this
-``get_template()`` call will attempt to load the following templates:
+example ``get_template()`` call will attempt to load the following templates:
 
 
 * ``/home/html/templates/lawrence.com/news/story_detail.html``
 * ``/home/html/templates/lawrence.com/news/story_detail.html``
 * ``/home/html/templates/default/news/story_detail.html``
 * ``/home/html/templates/default/news/story_detail.html``
@@ -976,7 +985,7 @@ in :ref:`settings-without-django-settings-module`. Simply import the appropriate
 pieces of the templating system and then, *before* you call any of the
 pieces of the templating system and then, *before* you call any of the
 templating functions, call :func:`django.conf.settings.configure()` with any
 templating functions, call :func:`django.conf.settings.configure()` with any
 settings you wish to specify. You might want to consider setting at least
 settings you wish to specify. You might want to consider setting at least
-:setting:`TEMPLATE_DIRS` (if you're going to use template loaders),
+:setting:`DIRS <TEMPLATES-DIRS>` (if you're going to use template loaders),
 :setting:`DEFAULT_CHARSET` (although the default of ``utf-8`` is probably fine)
 :setting:`DEFAULT_CHARSET` (although the default of ``utf-8`` is probably fine)
 and :setting:`TEMPLATE_DEBUG`. If you plan to use the :ttag:`url` template tag,
 and :setting:`TEMPLATE_DEBUG`. If you plan to use the :ttag:`url` template tag,
 you will also need to set the :setting:`ROOT_URLCONF` setting. All available
 you will also need to set the :setting:`ROOT_URLCONF` setting. All available

+ 1 - 1
docs/releases/1.7.txt

@@ -853,7 +853,7 @@ Templates
   rendering of a template.
   rendering of a template.
 
 
 * The following functions now accept a ``dirs`` parameter which is a list or
 * The following functions now accept a ``dirs`` parameter which is a list or
-  tuple to override :setting:`TEMPLATE_DIRS`:
+  tuple to override ``TEMPLATE_DIRS``:
 
 
   * :func:`django.template.loader.get_template()`
   * :func:`django.template.loader.get_template()`
   * :func:`django.template.loader.select_template()`
   * :func:`django.template.loader.select_template()`

+ 2 - 1
docs/releases/1.8.txt

@@ -1021,6 +1021,7 @@ As a consequence of the multiple template engines refactor, several settings
 are deprecated in favor of :setting:`TEMPLATES`:
 are deprecated in favor of :setting:`TEMPLATES`:
 
 
 * ``ALLOWED_INCLUDE_ROOTS``
 * ``ALLOWED_INCLUDE_ROOTS``
+* ``TEMPLATE_DIRS``
 * ``TEMPLATE_LOADERS``
 * ``TEMPLATE_LOADERS``
 * ``TEMPLATE_STRING_IF_INVALID``
 * ``TEMPLATE_STRING_IF_INVALID``
 
 
@@ -1249,7 +1250,7 @@ templates through the ``context`` dict.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
 The following functions will no longer accept a ``dirs`` parameter to override
 The following functions will no longer accept a ``dirs`` parameter to override
-:setting:`TEMPLATE_DIRS` in Django 2.0:
+``TEMPLATE_DIRS`` in Django 2.0:
 
 
 * :func:`django.template.loader.get_template()`
 * :func:`django.template.loader.get_template()`
 * :func:`django.template.loader.select_template()`
 * :func:`django.template.loader.select_template()`

+ 2 - 3
docs/topics/settings.txt

@@ -13,9 +13,9 @@ A settings file is just a Python module with module-level variables.
 
 
 Here are a couple of example settings::
 Here are a couple of example settings::
 
 
+    ALLOWED_HOSTS = ['www.example.com']
     DEBUG = False
     DEBUG = False
     DEFAULT_FROM_EMAIL = 'webmaster@example.com'
     DEFAULT_FROM_EMAIL = 'webmaster@example.com'
-    TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john')
 
 
 .. note::
 .. note::
 
 
@@ -188,8 +188,7 @@ Example::
 
 
     from django.conf import settings
     from django.conf import settings
 
 
-    settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
+    settings.configure(DEBUG=True, TEMPLATE_DEBUG=True)
-        TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base'))
 
 
 Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
 Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
 argument representing a setting and its value. Each argument name should be all
 argument representing a setting and its value. Each argument name should be all

+ 19 - 3
tests/admin_views/tests.py

@@ -6,7 +6,7 @@ import re
 import datetime
 import datetime
 import unittest
 import unittest
 
 
-from django.conf import settings, global_settings
+from django.conf import global_settings
 from django.core import mail
 from django.core import mail
 from django.core.checks import Error
 from django.core.checks import Error
 from django.core.files import temp as tempfile
 from django.core.files import temp as tempfile
@@ -62,7 +62,6 @@ from .admin import site, site2, CityAdmin
 
 
 ERROR_MESSAGE = "Please enter the correct username and password \
 ERROR_MESSAGE = "Please enter the correct username and password \
 for a staff account. Note that both fields may be case-sensitive."
 for a staff account. Note that both fields may be case-sensitive."
-ADMIN_VIEW_TEMPLATES_DIR = settings.TEMPLATE_DIRS + (os.path.join(os.path.dirname(upath(__file__)), 'templates'),)
 
 
 
 
 @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
 @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
@@ -788,7 +787,24 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
         self.assertContains(response, '<a href="/my-site-url/">View site</a>')
         self.assertContains(response, '<a href="/my-site-url/">View site</a>')
 
 
 
 
-@override_settings(TEMPLATE_DIRS=ADMIN_VIEW_TEMPLATES_DIR)
+@override_settings(TEMPLATES=[{
+    'BACKEND': 'django.template.backends.django.DjangoTemplates',
+    # Put this app's templates dir in DIRS to take precedence over the admin's
+    # templates dir.
+    'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
+    'APP_DIRS': True,
+    'OPTIONS': {
+        'context_processors': [
+            'django.template.context_processors.debug',
+            'django.template.context_processors.i18n',
+            'django.template.context_processors.tz',
+            'django.template.context_processors.media',
+            'django.template.context_processors.static',
+            'django.contrib.auth.context_processors.auth',
+            'django.contrib.messages.context_processors.messages',
+        ],
+    },
+}])
 class AdminCustomTemplateTests(AdminViewBasicTestCase):
 class AdminCustomTemplateTests(AdminViewBasicTestCase):
     def test_extended_bodyclass_template_change_form(self):
     def test_extended_bodyclass_template_change_form(self):
         """
         """

+ 9 - 3
tests/i18n/patterns/tests.py

@@ -21,9 +21,6 @@ class PermanentRedirectLocaleMiddleWare(LocaleMiddleware):
     LOCALE_PATHS=(
     LOCALE_PATHS=(
         os.path.join(os.path.dirname(upath(__file__)), 'locale'),
         os.path.join(os.path.dirname(upath(__file__)), 'locale'),
     ),
     ),
-    TEMPLATE_DIRS=(
-        os.path.join(os.path.dirname(upath(__file__)), 'templates'),
-    ),
     LANGUAGE_CODE='en-us',
     LANGUAGE_CODE='en-us',
     LANGUAGES=(
     LANGUAGES=(
         ('nl', 'Dutch'),
         ('nl', 'Dutch'),
@@ -35,6 +32,15 @@ class PermanentRedirectLocaleMiddleWare(LocaleMiddleware):
         'django.middleware.common.CommonMiddleware',
         'django.middleware.common.CommonMiddleware',
     ),
     ),
     ROOT_URLCONF='i18n.patterns.urls.default',
     ROOT_URLCONF='i18n.patterns.urls.default',
+    TEMPLATES=[{
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.i18n',
+            ],
+        },
+    }],
 )
 )
 class URLTestCaseBase(TestCase):
 class URLTestCaseBase(TestCase):
     """
     """

+ 7 - 4
tests/template_tests/test_response.py

@@ -208,10 +208,13 @@ class SimpleTemplateResponseTest(SimpleTestCase):
         self.assertEqual(unpickled_response.cookies['key'].value, 'value')
         self.assertEqual(unpickled_response.cookies['key'].value, 'value')
 
 
 
 
-@override_settings(
+@override_settings(TEMPLATES=[{
-    TEMPLATE_CONTEXT_PROCESSORS=[test_processor_name],
+    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates')),
+    'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
-)
+    'OPTIONS': {
+        'context_processors': [test_processor_name],
+    },
+}])
 class TemplateResponseTest(SimpleTestCase):
 class TemplateResponseTest(SimpleTestCase):
 
 
     def setUp(self):
     def setUp(self):

+ 3 - 6
tests/template_tests/tests.py

@@ -86,13 +86,11 @@ class TemplateLoaderTests(SimpleTestCase):
     # the compiled templates.
     # the compiled templates.
     @override_settings(TEMPLATE_DEBUG=True)
     @override_settings(TEMPLATE_DEBUG=True)
     def test_loader_debug_origin(self):
     def test_loader_debug_origin(self):
-        # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
-        # point to a directory containing a login.html file.
         load_name = 'login.html'
         load_name = 'login.html'
 
 
-        # We also rely on the fact the file system and app directories loaders
+        # We rely on the fact the file system and app directories loaders both
-        # both inherit the load_template method from the base Loader class, so
+        # inherit the load_template method from the base Loader class, so we
-        # we only need to test one of them.
+        # only need to test one of them.
         template = loader.get_template(load_name).template
         template = loader.get_template(load_name).template
         template_name = template.nodelist[0].source[0].name
         template_name = template.nodelist[0].source[0].name
         self.assertTrue(template_name.endswith(load_name),
         self.assertTrue(template_name.endswith(load_name),
@@ -111,7 +109,6 @@ class TemplateLoaderTests(SimpleTestCase):
     }])
     }])
     @override_settings(TEMPLATE_DEBUG=True)
     @override_settings(TEMPLATE_DEBUG=True)
     def test_cached_loader_debug_origin(self):
     def test_cached_loader_debug_origin(self):
-        # Same comment as in test_loader_debug_origin.
         load_name = 'login.html'
         load_name = 'login.html'
 
 
         # Test the cached loader separately since it overrides load_template.
         # Test the cached loader separately since it overrides load_template.

+ 5 - 7
tests/test_client_regress/tests.py

@@ -25,10 +25,7 @@ from .models import CustomUser
 from .views import CustomTestException
 from .views import CustomTestException
 
 
 
 
-@override_settings(
+@override_settings(ROOT_URLCONF='test_client_regress.urls')
-    TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'templates'),),
-    ROOT_URLCONF='test_client_regress.urls',
-)
 class AssertContainsTests(TestCase):
 class AssertContainsTests(TestCase):
 
 
     def test_contains(self):
     def test_contains(self):
@@ -911,9 +908,10 @@ class ExceptionTests(TestCase):
 @override_settings(ROOT_URLCONF='test_client_regress.urls')
 @override_settings(ROOT_URLCONF='test_client_regress.urls')
 class TemplateExceptionTests(TestCase):
 class TemplateExceptionTests(TestCase):
 
 
-    @override_settings(
+    @override_settings(TEMPLATES=[{
-        TEMPLATE_DIRS=(os.path.join(os.path.dirname(upath(__file__)), 'bad_templates'),)
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    )
+        'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'bad_templates')],
+    }])
     def test_bad_404_template(self):
     def test_bad_404_template(self):
         "Errors found when rendering 404 error templates are re-raised"
         "Errors found when rendering 404 error templates are re-raised"
         try:
         try:

+ 12 - 3
tests/view_tests/tests/test_debug.py

@@ -145,7 +145,10 @@ class DebugViewTests(TestCase):
         with NamedTemporaryFile(prefix=template_name) as tempfile:
         with NamedTemporaryFile(prefix=template_name) as tempfile:
             tempdir = os.path.dirname(tempfile.name)
             tempdir = os.path.dirname(tempfile.name)
             template_path = os.path.join(tempdir, template_name)
             template_path = os.path.join(tempdir, template_name)
-            with override_settings(TEMPLATE_DIRS=(tempdir,)):
+            with override_settings(TEMPLATES=[{
+                'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'DIRS': [tempdir],
+            }]):
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
             self.assertContains(response, "%s (File does not exist)" % template_path, status_code=500, count=1)
             self.assertContains(response, "%s (File does not exist)" % template_path, status_code=500, count=1)
 
 
@@ -157,7 +160,10 @@ class DebugViewTests(TestCase):
             tempdir = os.path.dirname(tempfile.name)
             tempdir = os.path.dirname(tempfile.name)
             template_path = os.path.join(tempdir, template_name)
             template_path = os.path.join(tempdir, template_name)
             os.chmod(template_path, 0o0222)
             os.chmod(template_path, 0o0222)
-            with override_settings(TEMPLATE_DIRS=(tempdir,)):
+            with override_settings(TEMPLATES=[{
+                'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'DIRS': [tempdir],
+            }]):
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
             self.assertContains(response, "%s (File is not readable)" % template_path, status_code=500, count=1)
             self.assertContains(response, "%s (File is not readable)" % template_path, status_code=500, count=1)
 
 
@@ -167,7 +173,10 @@ class DebugViewTests(TestCase):
             template_path = mkdtemp()
             template_path = mkdtemp()
             template_name = os.path.basename(template_path)
             template_name = os.path.basename(template_path)
             tempdir = os.path.dirname(template_path)
             tempdir = os.path.dirname(template_path)
-            with override_settings(TEMPLATE_DIRS=(tempdir,)):
+            with override_settings(TEMPLATES=[{
+                'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'DIRS': [tempdir],
+            }]):
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
                 response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
             self.assertContains(response, "%s (Not a file)" % template_path, status_code=500, count=1)
             self.assertContains(response, "%s (Not a file)" % template_path, status_code=500, count=1)
         finally:
         finally: