diff --git a/django/template/backends/django.py b/django/template/backends/django.py index a8dc2de300..580d789a67 100644 --- a/django/template/backends/django.py +++ b/django/template/backends/django.py @@ -3,7 +3,7 @@ from __future__ import absolute_import from django.conf import settings from django.template.context import Context, RequestContext -from django.template.engine import Engine +from django.template.engine import _dirs_undefined, Engine from .base import BaseEngine @@ -24,8 +24,8 @@ class DjangoTemplates(BaseEngine): def from_string(self, template_code): return Template(self.engine.from_string(template_code)) - def get_template(self, template_name): - return Template(self.engine.get_template(template_name)) + def get_template(self, template_name, dirs=_dirs_undefined): + return Template(self.engine.get_template(template_name, dirs)) class Template(object): @@ -33,9 +33,17 @@ class Template(object): def __init__(self, template): self.template = template + @property + def origin(self): + # TODO: define the Origin API. For now simply forwarding to the + # underlying Template preserves backwards-compatibility. + return self.template.origin + def render(self, context=None, request=None): - if request is None: - context = Context(context) - else: - context = RequestContext(request, context) + # TODO: require context to be a dict -- through a deprecation path? + if not isinstance(context, Context): + if request is None: + context = Context(context) + else: + context = RequestContext(request, context) return self.template.render(context) diff --git a/django/template/base.py b/django/template/base.py index 42c0047079..3d538cb69e 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -1266,6 +1266,8 @@ class Library(object): if not getattr(self, 'nodelist', False): if isinstance(file_name, Template): t = file_name + elif isinstance(getattr(file_name, 'template', None), Template): + t = file_name.template elif not isinstance(file_name, six.string_types) and is_iterable(file_name): t = context.engine.select_template(file_name) else: diff --git a/django/template/loader.py b/django/template/loader.py index d7c42627d1..b76fbdcfb9 100644 --- a/django/template/loader.py +++ b/django/template/loader.py @@ -2,8 +2,10 @@ import warnings from django.utils.deprecation import RemovedInDjango20Warning -from .base import Origin -from .engine import Engine +from . import engines +from .backends.django import DjangoTemplates +from .base import Origin, TemplateDoesNotExist +from .engine import _dirs_undefined, Engine class LoaderOrigin(Origin): @@ -19,8 +21,62 @@ def find_template(*args, **kwargs): return Engine.get_default().find_template(*args, **kwargs) -def get_template(*args, **kwargs): - return Engine.get_default().get_template(*args, **kwargs) +def get_template(template_name, dirs=_dirs_undefined, using=None): + """ + Loads and returns a template for the given name. + + Raises TemplateDoesNotExist if no such template exists. + """ + engines = _engine_list(using) + for engine in engines: + try: + # This is required for deprecating the dirs argument. Simply + # return engine.get_template(template_name) in Django 2.0. + if isinstance(engine, DjangoTemplates): + return engine.get_template(template_name, dirs) + elif dirs is not _dirs_undefined: + warnings.warn( + "Skipping template backend %s because its get_template " + "method doesn't support the dirs argument." % engine.name, + stacklevel=2) + else: + return engine.get_template(template_name) + except TemplateDoesNotExist: + pass + + raise TemplateDoesNotExist(template_name) + + +def select_template(template_name_list, dirs=_dirs_undefined, using=None): + """ + Loads and returns a template for one of the given names. + + Tries names in order and returns the first template found. + + Raises TemplateDoesNotExist if no such template exists. + """ + engines = _engine_list(using) + for template_name in template_name_list: + for engine in engines: + try: + # This is required for deprecating the dirs argument. Simply + # use engine.get_template(template_name) in Django 2.0. + if isinstance(engine, DjangoTemplates): + return engine.get_template(template_name, dirs) + elif dirs is not _dirs_undefined: + warnings.warn( + "Skipping template backend %s because its get_template " + "method doesn't support the dirs argument." % engine.name, + stacklevel=2) + else: + return engine.get_template(template_name) + except TemplateDoesNotExist: + pass + + if template_name_list: + raise TemplateDoesNotExist(', '.join(template_name_list)) + else: + raise TemplateDoesNotExist("No template names provided") def get_template_from_string(*args, **kwargs): @@ -31,8 +87,8 @@ def render_to_string(*args, **kwargs): return Engine.get_default().render_to_string(*args, **kwargs) -def select_template(*args, **kwargs): - return Engine.get_default().select_template(*args, **kwargs) +def _engine_list(using=None): + return engines.all() if using is None else [engines[using]] # This line must remain at the bottom to avoid import loops. diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py index 80f926ea6f..5d4b029430 100644 --- a/tests/template_tests/tests.py +++ b/tests/template_tests/tests.py @@ -85,7 +85,7 @@ class TemplateLoaderTests(SimpleTestCase): # We also rely on the fact the file system and app directories loaders # both inherit the load_template method from the base Loader class, so # we only need to test one of them. - template = loader.get_template(load_name) + template = loader.get_template(load_name).template template_name = template.nodelist[0].source[0].name self.assertTrue(template_name.endswith(load_name), 'Template loaded by filesystem loader has incorrect name for debug page: %s' % template_name) @@ -100,12 +100,12 @@ class TemplateLoaderTests(SimpleTestCase): load_name = 'login.html' # Test the cached loader separately since it overrides load_template. - template = loader.get_template(load_name) + template = loader.get_template(load_name).template template_name = template.nodelist[0].source[0].name self.assertTrue(template_name.endswith(load_name), 'Template loaded through cached loader has incorrect name for debug page: %s' % template_name) - template = loader.get_template(load_name) + template = loader.get_template(load_name).template template_name = template.nodelist[0].source[0].name self.assertTrue(template_name.endswith(load_name), 'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name)