1
# Wrapper for loading templates from storage of some sort (e.g. filesystem, database).
3
# This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
4
# Each loader is expected to have this interface:
6
# callable(name, dirs=[])
8
# name is the template name.
9
# dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
11
# The loader should return a tuple of (template_source, path). The path returned
12
# might be shown to the user for debugging purposes, so it should identify where
13
# the template was loaded from.
15
# Each loader should have an "is_usable" attribute set. This is a boolean that
16
# specifies whether the loader can be used in this Python installation. Each
17
# loader is responsible for setting this when it's initialized.
19
# For example, the eggs loader (which is capable of loading templates from
20
# Python eggs) sets is_usable to False if the "pkg_resources" module isn't
21
# installed, because pkg_resources is necessary to read eggs.
23
from django.core.exceptions import ImproperlyConfigured
24
from django.template import Origin, StringOrigin, Template, Context, TemplateDoesNotExist, add_to_builtins
25
from django.conf import settings
27
template_source_loaders = None
29
class LoaderOrigin(Origin):
30
def __init__(self, display_name, loader, name, dirs):
31
super(LoaderOrigin, self).__init__(display_name)
32
self.loader, self.loadname, self.dirs = loader, name, dirs
35
return self.loader(self.loadname, self.dirs)[0]
37
def make_origin(display_name, loader, name, dirs):
38
if settings.TEMPLATE_DEBUG:
39
return LoaderOrigin(display_name, loader, name, dirs)
43
def find_template_source(name, dirs=None):
44
# Calculate template_source_loaders the first time the function is executed
45
# because putting this logic in the module-level namespace may cause
46
# circular import errors. See Django ticket #1292.
47
global template_source_loaders
48
if template_source_loaders is None:
49
template_source_loaders = []
50
for path in settings.TEMPLATE_LOADERS:
52
module, attr = path[:i], path[i+1:]
54
mod = __import__(module, globals(), locals(), [attr])
55
except ImportError, e:
56
raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
58
func = getattr(mod, attr)
59
except AttributeError:
60
raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
61
if not func.is_usable:
63
warnings.warn("Your TEMPLATE_LOADERS setting includes %r, but your Python installation doesn't support that type of template loading. Consider removing that line from TEMPLATE_LOADERS." % path)
65
template_source_loaders.append(func)
66
for loader in template_source_loaders:
68
source, display_name = loader(name, dirs)
69
return (source, make_origin(display_name, loader, name, dirs))
70
except TemplateDoesNotExist:
72
raise TemplateDoesNotExist, name
74
def get_template(template_name):
76
Returns a compiled Template object for the given template name,
77
handling template inheritance recursively.
79
return get_template_from_string(*find_template_source(template_name))
81
def get_template_from_string(source, origin=None):
83
Returns a compiled Template object for the given template code,
84
handling template inheritance recursively.
86
return Template(source, origin)
88
def render_to_string(template_name, dictionary=None, context_instance=None):
90
Loads the given template_name and renders it with the given dictionary as
91
context. The template_name may be a string to load a single template using
92
get_template, or it may be a tuple to use select_template to find one of
93
the templates in the list. Returns a string.
95
dictionary = dictionary or {}
96
if isinstance(template_name, (list, tuple)):
97
t = select_template(template_name)
99
t = get_template(template_name)
101
context_instance.update(dictionary)
103
context_instance = Context(dictionary)
104
return t.render(context_instance)
106
def select_template(template_name_list):
107
"Given a list of template names, returns the first that can be loaded."
108
for template_name in template_name_list:
110
return get_template(template_name)
111
except TemplateDoesNotExist:
113
# If we get here, none of the templates could be loaded
114
raise TemplateDoesNotExist, ', '.join(template_name_list)
116
add_to_builtins('django.template.loader_tags')