diff -r 8d941af65caf -r 77b6da96e6f1 web/lib/django/template/loader.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/django/template/loader.py Wed Jun 02 18:57:35 2010 +0200 @@ -0,0 +1,198 @@ +# Wrapper for loading templates from storage of some sort (e.g. filesystem, database). +# +# This uses the TEMPLATE_LOADERS setting, which is a list of loaders to use. +# Each loader is expected to have this interface: +# +# callable(name, dirs=[]) +# +# name is the template name. +# dirs is an optional list of directories to search instead of TEMPLATE_DIRS. +# +# The loader should return a tuple of (template_source, path). The path returned +# 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. +# +# For example, the eggs loader (which is capable of loading templates from +# Python eggs) sets is_usable to False if the "pkg_resources" module isn't +# installed, because pkg_resources is necessary to read eggs. + +from django.core.exceptions import ImproperlyConfigured +from django.template import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins +from django.utils.importlib import import_module +from django.conf import settings + +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) + self.loader, self.loadname, self.dirs = loader, name, dirs + + def reload(self): + return self.loader(self.loadname, self.dirs)[0] + +def make_origin(display_name, loader, name, dirs): + if settings.TEMPLATE_DEBUG and display_name: + return LoaderOrigin(display_name, loader, name, dirs) + else: + return 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 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: + source, display_name = loader(name, dirs) + return (source, make_origin(display_name, loader, name, dirs)) + except TemplateDoesNotExist: + pass + 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. + """ + 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): + """ + Returns a compiled Template object for the given template code, + handling template inheritance recursively. + """ + return Template(source, origin, name) + +def render_to_string(template_name, dictionary=None, context_instance=None): + """ + Loads the given template_name and renders it with the given dictionary as + context. The template_name may be a string to load a single template using + get_template, or it may be a tuple to use select_template to find one of + the templates in the list. Returns a string. + """ + dictionary = dictionary or {} + if isinstance(template_name, (list, tuple)): + t = select_template(template_name) + else: + t = get_template(template_name) + if context_instance: + context_instance.update(dictionary) + else: + context_instance = Context(dictionary) + return t.render(context_instance) + +def select_template(template_name_list): + "Given a list of template names, returns the first that can be loaded." + for template_name in template_name_list: + try: + return get_template(template_name) + except TemplateDoesNotExist: + continue + # If we get here, none of the templates could be loaded + raise TemplateDoesNotExist(', '.join(template_name_list)) + +add_to_builtins('django.template.loader_tags')