Django

Code

root/django/trunk/django/template/loader.py

Revision 10088, 4.9 kB (checked in by jacob, 4 months ago)

Fixed #8193: all dynamic imports in Django are now done correctly. I know this because Brett Cannon borrowed the time machine and brought Python 2.7's 'importlib back for inclusion in Django. Thanks for the patch-from-the-future, Brett!

  • Property svn:eol-style set to native
Line 
1 # Wrapper for loading templates from storage of some sort (e.g. filesystem, database).
2 #
3 # This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use.
4 # Each loader is expected to have this interface:
5 #
6 #    callable(name, dirs=[])
7 #
8 # name is the template name.
9 # dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
10 #
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.
14 #
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.
18 #
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.
22
23 from django.core.exceptions import ImproperlyConfigured
24 from django.template import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins
25 from django.utils.importlib import import_module
26 from django.conf import settings
27
28 template_source_loaders = None
29
30 class LoaderOrigin(Origin):
31     def __init__(self, display_name, loader, name, dirs):
32         super(LoaderOrigin, self).__init__(display_name)
33         self.loader, self.loadname, self.dirs = loader, name, dirs
34
35     def reload(self):
36         return self.loader(self.loadname, self.dirs)[0]
37
38 def make_origin(display_name, loader, name, dirs):
39     if settings.TEMPLATE_DEBUG:
40         return LoaderOrigin(display_name, loader, name, dirs)
41     else:
42         return None
43
44 def find_template_source(name, dirs=None):
45     # Calculate template_source_loaders the first time the function is executed
46     # because putting this logic in the module-level namespace may cause
47     # circular import errors. See Django ticket #1292.
48     global template_source_loaders
49     if template_source_loaders is None:
50         loaders = []
51         for path in settings.TEMPLATE_LOADERS:
52             i = path.rfind('.')
53             module, attr = path[:i], path[i+1:]
54             try:
55                 mod = import_module(module)
56             except ImportError, e:
57                 raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
58             try:
59                 func = getattr(mod, attr)
60             except AttributeError:
61                 raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
62             if not func.is_usable:
63                 import warnings
64                 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             else:
66                 loaders.append(func)
67         template_source_loaders = tuple(loaders)
68     for loader in template_source_loaders:
69         try:
70             source, display_name = loader(name, dirs)
71             return (source, make_origin(display_name, loader, name, dirs))
72         except TemplateDoesNotExist:
73             pass
74     raise TemplateDoesNotExist, name
75
76 def get_template(template_name):
77     """
78     Returns a compiled Template object for the given template name,
79     handling template inheritance recursively.
80     """
81     source, origin = find_template_source(template_name)
82     template = get_template_from_string(source, origin, template_name)
83     return template
84
85 def get_template_from_string(source, origin=None, name=None):
86     """
87     Returns a compiled Template object for the given template code,
88     handling template inheritance recursively.
89     """
90     return Template(source, origin, name)
91
92 def render_to_string(template_name, dictionary=None, context_instance=None):
93     """
94     Loads the given template_name and renders it with the given dictionary as
95     context. The template_name may be a string to load a single template using
96     get_template, or it may be a tuple to use select_template to find one of
97     the templates in the list. Returns a string.
98     """
99     dictionary = dictionary or {}
100     if isinstance(template_name, (list, tuple)):
101         t = select_template(template_name)
102     else:
103         t = get_template(template_name)
104     if context_instance:
105         context_instance.update(dictionary)
106     else:
107         context_instance = Context(dictionary)
108     return t.render(context_instance)
109
110 def select_template(template_name_list):
111     "Given a list of template names, returns the first that can be loaded."
112     for template_name in template_name_list:
113         try:
114             return get_template(template_name)
115         except TemplateDoesNotExist:
116             continue
117     # If we get here, none of the templates could be loaded
118     raise TemplateDoesNotExist, ', '.join(template_name_list)
119
120 add_to_builtins('django.template.loader_tags')
Note: See TracBrowser for help on using the browser.