1
0
mirror of https://github.com/django/django.git synced 2025-04-01 12:06:43 +00:00

Fixed #27359 -- Made Engine.get_default() return the first DjangoTemplates engine if multiple are defined.

This commit is contained in:
Carlton Gibson 2017-03-10 21:46:37 +01:00 committed by Tim Graham
parent 7019724101
commit 6b3724fa11
5 changed files with 27 additions and 25 deletions

View File

@ -141,6 +141,7 @@ answer newbie questions, and generally made Django that much better:
Carl Meyer <carl@oddbird.net> Carl Meyer <carl@oddbird.net>
Carlos Eduardo de Paula <carlosedp@gmail.com> Carlos Eduardo de Paula <carlosedp@gmail.com>
Carlos Matías de la Torre <cmdelatorre@gmail.com> Carlos Matías de la Torre <cmdelatorre@gmail.com>
Carlton Gibson <carlton.gibson@noumenal.es>
cedric@terramater.net cedric@terramater.net
ChaosKCW ChaosKCW
Charlie Leifer <coleifer@gmail.com> Charlie Leifer <coleifer@gmail.com>

View File

@ -56,9 +56,8 @@ class Engine:
@functools.lru_cache() @functools.lru_cache()
def get_default(): def get_default():
""" """
When only one DjangoTemplates backend is configured, return it. Return the first DjangoTemplates backend that's configured, or raise
ImproperlyConfigured if none are configured.
Raise ImproperlyConfigured otherwise.
This is required for preserving historical APIs that rely on a This is required for preserving historical APIs that rely on a
globally available, implicitly configured engine such as: globally available, implicitly configured engine such as:
@ -74,18 +73,10 @@ class Engine:
# local imports are required to avoid import loops. # local imports are required to avoid import loops.
from django.template import engines from django.template import engines
from django.template.backends.django import DjangoTemplates from django.template.backends.django import DjangoTemplates
django_engines = [engine for engine in engines.all() for engine in engines.all():
if isinstance(engine, DjangoTemplates)] if isinstance(engine, DjangoTemplates):
if len(django_engines) == 1: return engine.engine
# Unwrap the Engine instance inside DjangoTemplates raise ImproperlyConfigured('No DjangoTemplates backend is configured.')
return django_engines[0].engine
elif len(django_engines) == 0:
raise ImproperlyConfigured(
"No DjangoTemplates backend is configured.")
else:
raise ImproperlyConfigured(
"Several DjangoTemplates backends are configured. "
"You must select one explicitly.")
@cached_property @cached_property
def template_context_processors(self): def template_context_processors(self):

View File

@ -146,14 +146,20 @@ what's passed by :class:`~django.template.backends.django.DjangoTemplates`.
.. staticmethod:: Engine.get_default() .. staticmethod:: Engine.get_default()
When a Django project configures one and only one Returns the underlying :class:`Engine` from the first configured
:class:`~django.template.backends.django.DjangoTemplates` engine, this :class:`~django.template.backends.django.DjangoTemplates` engine. Raises
method returns the underlying :class:`Engine`. In other circumstances it :exc:`~django.core.exceptions.ImproperlyConfigured` if no engines are
will raise :exc:`~django.core.exceptions.ImproperlyConfigured`. configured.
It's required for preserving APIs that rely on a globally available, It's required for preserving APIs that rely on a globally available,
implicitly configured engine. Any other use is strongly discouraged. implicitly configured engine. Any other use is strongly discouraged.
.. versionchanged:: 2.0
In older versions, raises
:exc:`~django.core.exceptions.ImproperlyConfigured` if multiple
engines are configured rather than returning the first engine.
.. method:: Engine.from_string(template_code) .. method:: Engine.from_string(template_code)
Compiles the given template code and returns a :class:`Template` object. Compiles the given template code and returns a :class:`Template` object.
@ -175,9 +181,11 @@ The recommended way to create a :class:`Template` is by calling the factory
methods of the :class:`Engine`: :meth:`~Engine.get_template`, methods of the :class:`Engine`: :meth:`~Engine.get_template`,
:meth:`~Engine.select_template` and :meth:`~Engine.from_string`. :meth:`~Engine.select_template` and :meth:`~Engine.from_string`.
In a Django project where the :setting:`TEMPLATES` setting defines exactly one In a Django project where the :setting:`TEMPLATES` setting defines a
:class:`~django.template.backends.django.DjangoTemplates` engine, it's :class:`~django.template.backends.django.DjangoTemplates` engine, it's
possible to instantiate a :class:`Template` directly. possible to instantiate a :class:`Template` directly. If more than one
:class:`~django.template.backends.django.DjangoTemplates` engine is defined,
the first one will be used.
.. class:: Template .. class:: Template

View File

@ -191,7 +191,9 @@ Signals
Templates Templates
~~~~~~~~~ ~~~~~~~~~
* ... * To increase the usefulness of :meth:`.Engine.get_default` in third-party
apps, it now returns the first engine if multiple ``DjangoTemplates`` engines
are configured in ``TEMPLATES`` rather than raising ``ImproperlyConfigured``.
Tests Tests
~~~~~ ~~~~~

View File

@ -41,14 +41,14 @@ class GetDefaultTests(SimpleTestCase):
@override_settings(TEMPLATES=[{ @override_settings(TEMPLATES=[{
'NAME': 'default', 'NAME': 'default',
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {'file_charset': 'abc'},
}, { }, {
'NAME': 'other', 'NAME': 'other',
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {'file_charset': 'def'},
}]) }])
def test_multiple_engines_configured(self): def test_multiple_engines_configured(self):
msg = 'Several DjangoTemplates backends are configured. You must select one explicitly.' self.assertEqual(Engine.get_default().file_charset, 'abc')
with self.assertRaisesMessage(ImproperlyConfigured, msg):
Engine.get_default()
class LoaderTests(SimpleTestCase): class LoaderTests(SimpleTestCase):