web/lib/django/template/loader.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     9 # dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
     9 # dirs is an optional list of directories to search instead of TEMPLATE_DIRS.
    10 #
    10 #
    11 # The loader should return a tuple of (template_source, path). The path returned
    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
    12 # might be shown to the user for debugging purposes, so it should identify where
    13 # the template was loaded from.
    13 # the template was loaded from.
       
    14 #
       
    15 # A loader may return an already-compiled template instead of the actual
       
    16 # template source. In that case the path returned should be None, since the
       
    17 # path information is associated with the template during the compilation,
       
    18 # which has already been done.
    14 #
    19 #
    15 # Each loader should have an "is_usable" attribute set. This is a boolean that
    20 # 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
    21 # specifies whether the loader can be used in this Python installation. Each
    17 # loader is responsible for setting this when it's initialized.
    22 # loader is responsible for setting this when it's initialized.
    18 #
    23 #
    25 from django.utils.importlib import import_module
    30 from django.utils.importlib import import_module
    26 from django.conf import settings
    31 from django.conf import settings
    27 
    32 
    28 template_source_loaders = None
    33 template_source_loaders = None
    29 
    34 
       
    35 class BaseLoader(object):
       
    36     is_usable = False
       
    37 
       
    38     def __init__(self, *args, **kwargs):
       
    39         pass
       
    40 
       
    41     def __call__(self, template_name, template_dirs=None):
       
    42         return self.load_template(template_name, template_dirs)
       
    43 
       
    44     def load_template(self, template_name, template_dirs=None):
       
    45         source, display_name = self.load_template_source(template_name, template_dirs)
       
    46         origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
       
    47         try:
       
    48             template = get_template_from_string(source, origin, template_name)
       
    49             return template, None
       
    50         except TemplateDoesNotExist:
       
    51             # If compiling the template we found raises TemplateDoesNotExist, back off to
       
    52             # returning the source and display name for the template we were asked to load.
       
    53             # This allows for correct identification (later) of the actual template that does
       
    54             # not exist.
       
    55             return source, display_name
       
    56 
       
    57     def load_template_source(self, template_name, template_dirs=None):
       
    58         """
       
    59         Returns a tuple containing the source and origin for the given template
       
    60         name.
       
    61 
       
    62         """
       
    63         raise NotImplementedError
       
    64 
       
    65     def reset(self):
       
    66         """
       
    67         Resets any state maintained by the loader instance (e.g., cached
       
    68         templates or cached loader modules).
       
    69 
       
    70         """
       
    71         pass
       
    72 
    30 class LoaderOrigin(Origin):
    73 class LoaderOrigin(Origin):
    31     def __init__(self, display_name, loader, name, dirs):
    74     def __init__(self, display_name, loader, name, dirs):
    32         super(LoaderOrigin, self).__init__(display_name)
    75         super(LoaderOrigin, self).__init__(display_name)
    33         self.loader, self.loadname, self.dirs = loader, name, dirs
    76         self.loader, self.loadname, self.dirs = loader, name, dirs
    34 
    77 
    35     def reload(self):
    78     def reload(self):
    36         return self.loader(self.loadname, self.dirs)[0]
    79         return self.loader(self.loadname, self.dirs)[0]
    37 
    80 
    38 def make_origin(display_name, loader, name, dirs):
    81 def make_origin(display_name, loader, name, dirs):
    39     if settings.TEMPLATE_DEBUG:
    82     if settings.TEMPLATE_DEBUG and display_name:
    40         return LoaderOrigin(display_name, loader, name, dirs)
    83         return LoaderOrigin(display_name, loader, name, dirs)
    41     else:
    84     else:
    42         return None
    85         return None
    43 
    86 
    44 def find_template_source(name, dirs=None):
    87 def find_template_loader(loader):
       
    88     if isinstance(loader, (tuple, list)):
       
    89         loader, args = loader[0], loader[1:]
       
    90     else:
       
    91         args = []
       
    92     if isinstance(loader, basestring):
       
    93         module, attr = loader.rsplit('.', 1)
       
    94         try:
       
    95             mod = import_module(module)
       
    96         except ImportError, e:
       
    97             raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
       
    98         try:
       
    99             TemplateLoader = getattr(mod, attr)
       
   100         except AttributeError, e:
       
   101             raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
       
   102 
       
   103         if hasattr(TemplateLoader, 'load_template_source'):
       
   104             func = TemplateLoader(*args)
       
   105         else:
       
   106             # Try loading module the old way - string is full path to callable
       
   107             if args:
       
   108                 raise ImproperlyConfigured("Error importing template source loader %s - can't pass arguments to function-based loader." % loader)
       
   109             func = TemplateLoader
       
   110 
       
   111         if not func.is_usable:
       
   112             import warnings
       
   113             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)
       
   114             return None
       
   115         else:
       
   116             return func
       
   117     else:
       
   118         raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader')
       
   119 
       
   120 def find_template(name, dirs=None):
    45     # Calculate template_source_loaders the first time the function is executed
   121     # Calculate template_source_loaders the first time the function is executed
    46     # because putting this logic in the module-level namespace may cause
   122     # because putting this logic in the module-level namespace may cause
    47     # circular import errors. See Django ticket #1292.
   123     # circular import errors. See Django ticket #1292.
    48     global template_source_loaders
   124     global template_source_loaders
    49     if template_source_loaders is None:
   125     if template_source_loaders is None:
    50         loaders = []
   126         loaders = []
    51         for path in settings.TEMPLATE_LOADERS:
   127         for loader_name in settings.TEMPLATE_LOADERS:
    52             i = path.rfind('.')
   128             loader = find_template_loader(loader_name)
    53             module, attr = path[:i], path[i+1:]
   129             if loader is not None:
    54             try:
   130                 loaders.append(loader)
    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)
   131         template_source_loaders = tuple(loaders)
    68     for loader in template_source_loaders:
   132     for loader in template_source_loaders:
    69         try:
   133         try:
    70             source, display_name = loader(name, dirs)
   134             source, display_name = loader(name, dirs)
    71             return (source, make_origin(display_name, loader, name, dirs))
   135             return (source, make_origin(display_name, loader, name, dirs))
    72         except TemplateDoesNotExist:
   136         except TemplateDoesNotExist:
    73             pass
   137             pass
    74     raise TemplateDoesNotExist, name
   138     raise TemplateDoesNotExist(name)
       
   139 
       
   140 def find_template_source(name, dirs=None):
       
   141     # For backward compatibility
       
   142     import warnings
       
   143     warnings.warn(
       
   144         "`django.template.loaders.find_template_source` is deprecated; use `django.template.loaders.find_template` instead.",
       
   145         PendingDeprecationWarning
       
   146     )
       
   147     template, origin = find_template(name, dirs)
       
   148     if hasattr(template, 'render'):
       
   149         raise Exception("Found a compiled template that is incompatible with the deprecated `django.template.loaders.find_template_source` function.")
       
   150     return template, origin
    75 
   151 
    76 def get_template(template_name):
   152 def get_template(template_name):
    77     """
   153     """
    78     Returns a compiled Template object for the given template name,
   154     Returns a compiled Template object for the given template name,
    79     handling template inheritance recursively.
   155     handling template inheritance recursively.
    80     """
   156     """
    81     source, origin = find_template_source(template_name)
   157     template, origin = find_template(template_name)
    82     template = get_template_from_string(source, origin, template_name)
   158     if not hasattr(template, 'render'):
       
   159         # template needs to be compiled
       
   160         template = get_template_from_string(template, origin, template_name)
    83     return template
   161     return template
    84 
   162 
    85 def get_template_from_string(source, origin=None, name=None):
   163 def get_template_from_string(source, origin=None, name=None):
    86     """
   164     """
    87     Returns a compiled Template object for the given template code,
   165     Returns a compiled Template object for the given template code,
   113         try:
   191         try:
   114             return get_template(template_name)
   192             return get_template(template_name)
   115         except TemplateDoesNotExist:
   193         except TemplateDoesNotExist:
   116             continue
   194             continue
   117     # If we get here, none of the templates could be loaded
   195     # If we get here, none of the templates could be loaded
   118     raise TemplateDoesNotExist, ', '.join(template_name_list)
   196     raise TemplateDoesNotExist(', '.join(template_name_list))
   119 
   197 
   120 add_to_builtins('django.template.loader_tags')
   198 add_to_builtins('django.template.loader_tags')