--- a/web/lib/django/template/loader.py Wed May 19 17:43:59 2010 +0200
+++ b/web/lib/django/template/loader.py Tue May 25 02:43:45 2010 +0200
@@ -12,6 +12,11 @@
# might be shown to the user for debugging purposes, so it should identify where
# the template was loaded from.
#
+# A loader may return an already-compiled template instead of the actual
+# template source. In that case the path returned should be None, since the
+# path information is associated with the template during the compilation,
+# which has already been done.
+#
# Each loader should have an "is_usable" attribute set. This is a boolean that
# specifies whether the loader can be used in this Python installation. Each
# loader is responsible for setting this when it's initialized.
@@ -27,6 +32,44 @@
template_source_loaders = None
+class BaseLoader(object):
+ is_usable = False
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def __call__(self, template_name, template_dirs=None):
+ return self.load_template(template_name, template_dirs)
+
+ def load_template(self, template_name, template_dirs=None):
+ source, display_name = self.load_template_source(template_name, template_dirs)
+ origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
+ try:
+ template = get_template_from_string(source, origin, template_name)
+ return template, None
+ except TemplateDoesNotExist:
+ # If compiling the template we found raises TemplateDoesNotExist, back off to
+ # returning the source and display name for the template we were asked to load.
+ # This allows for correct identification (later) of the actual template that does
+ # not exist.
+ return source, display_name
+
+ def load_template_source(self, template_name, template_dirs=None):
+ """
+ Returns a tuple containing the source and origin for the given template
+ name.
+
+ """
+ raise NotImplementedError
+
+ def reset(self):
+ """
+ Resets any state maintained by the loader instance (e.g., cached
+ templates or cached loader modules).
+
+ """
+ pass
+
class LoaderOrigin(Origin):
def __init__(self, display_name, loader, name, dirs):
super(LoaderOrigin, self).__init__(display_name)
@@ -36,34 +79,55 @@
return self.loader(self.loadname, self.dirs)[0]
def make_origin(display_name, loader, name, dirs):
- if settings.TEMPLATE_DEBUG:
+ if settings.TEMPLATE_DEBUG and display_name:
return LoaderOrigin(display_name, loader, name, dirs)
else:
return None
-def find_template_source(name, dirs=None):
+def find_template_loader(loader):
+ if isinstance(loader, (tuple, list)):
+ loader, args = loader[0], loader[1:]
+ else:
+ args = []
+ if isinstance(loader, basestring):
+ module, attr = loader.rsplit('.', 1)
+ try:
+ mod = import_module(module)
+ except ImportError, e:
+ raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
+ try:
+ TemplateLoader = getattr(mod, attr)
+ except AttributeError, e:
+ raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
+
+ if hasattr(TemplateLoader, 'load_template_source'):
+ func = TemplateLoader(*args)
+ else:
+ # Try loading module the old way - string is full path to callable
+ if args:
+ raise ImproperlyConfigured("Error importing template source loader %s - can't pass arguments to function-based loader." % loader)
+ func = TemplateLoader
+
+ if not func.is_usable:
+ import warnings
+ 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." % loader)
+ return None
+ else:
+ return func
+ else:
+ raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader')
+
+def find_template(name, dirs=None):
# Calculate template_source_loaders the first time the function is executed
# because putting this logic in the module-level namespace may cause
# circular import errors. See Django ticket #1292.
global template_source_loaders
if template_source_loaders is None:
loaders = []
- for path in settings.TEMPLATE_LOADERS:
- i = path.rfind('.')
- module, attr = path[:i], path[i+1:]
- try:
- mod = import_module(module)
- except ImportError, e:
- raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
- try:
- func = getattr(mod, attr)
- except AttributeError:
- raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr)
- if not func.is_usable:
- import warnings
- 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)
- else:
- loaders.append(func)
+ for loader_name in settings.TEMPLATE_LOADERS:
+ loader = find_template_loader(loader_name)
+ if loader is not None:
+ loaders.append(loader)
template_source_loaders = tuple(loaders)
for loader in template_source_loaders:
try:
@@ -71,15 +135,29 @@
return (source, make_origin(display_name, loader, name, dirs))
except TemplateDoesNotExist:
pass
- raise TemplateDoesNotExist, name
+ raise TemplateDoesNotExist(name)
+
+def find_template_source(name, dirs=None):
+ # For backward compatibility
+ import warnings
+ warnings.warn(
+ "`django.template.loaders.find_template_source` is deprecated; use `django.template.loaders.find_template` instead.",
+ PendingDeprecationWarning
+ )
+ template, origin = find_template(name, dirs)
+ if hasattr(template, 'render'):
+ raise Exception("Found a compiled template that is incompatible with the deprecated `django.template.loaders.find_template_source` function.")
+ return template, origin
def get_template(template_name):
"""
Returns a compiled Template object for the given template name,
handling template inheritance recursively.
"""
- source, origin = find_template_source(template_name)
- template = get_template_from_string(source, origin, template_name)
+ template, origin = find_template(template_name)
+ if not hasattr(template, 'render'):
+ # template needs to be compiled
+ template = get_template_from_string(template, origin, template_name)
return template
def get_template_from_string(source, origin=None, name=None):
@@ -115,6 +193,6 @@
except TemplateDoesNotExist:
continue
# If we get here, none of the templates could be loaded
- raise TemplateDoesNotExist, ', '.join(template_name_list)
+ raise TemplateDoesNotExist(', '.join(template_name_list))
add_to_builtins('django.template.loader_tags')