web/lib/django/template/loaders/app_directories.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 """
       
     2 Wrapper for loading templates from "templates" directories in INSTALLED_APPS
       
     3 packages.
       
     4 """
       
     5 
       
     6 import os
       
     7 import sys
       
     8 
       
     9 from django.conf import settings
       
    10 from django.core.exceptions import ImproperlyConfigured
       
    11 from django.template import TemplateDoesNotExist
       
    12 from django.template.loader import BaseLoader
       
    13 from django.utils._os import safe_join
       
    14 from django.utils.importlib import import_module
       
    15 
       
    16 # At compile time, cache the directories to search.
       
    17 fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
       
    18 app_template_dirs = []
       
    19 for app in settings.INSTALLED_APPS:
       
    20     try:
       
    21         mod = import_module(app)
       
    22     except ImportError, e:
       
    23         raise ImproperlyConfigured('ImportError %s: %s' % (app, e.args[0]))
       
    24     template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
       
    25     if os.path.isdir(template_dir):
       
    26         app_template_dirs.append(template_dir.decode(fs_encoding))
       
    27 
       
    28 # It won't change, so convert it to a tuple to save memory.
       
    29 app_template_dirs = tuple(app_template_dirs)
       
    30 
       
    31 class Loader(BaseLoader):
       
    32     is_usable = True
       
    33 
       
    34     def get_template_sources(self, template_name, template_dirs=None):
       
    35         """
       
    36         Returns the absolute paths to "template_name", when appended to each
       
    37         directory in "template_dirs". Any paths that don't lie inside one of the
       
    38         template dirs are excluded from the result set, for security reasons.
       
    39         """
       
    40         if not template_dirs:
       
    41             template_dirs = app_template_dirs
       
    42         for template_dir in template_dirs:
       
    43             try:
       
    44                 yield safe_join(template_dir, template_name)
       
    45             except UnicodeDecodeError:
       
    46                 # The template dir name was a bytestring that wasn't valid UTF-8.
       
    47                 raise
       
    48             except ValueError:
       
    49                 # The joined path was located outside of template_dir.
       
    50                 pass
       
    51 
       
    52     def load_template_source(self, template_name, template_dirs=None):
       
    53         for filepath in self.get_template_sources(template_name, template_dirs):
       
    54             try:
       
    55                 file = open(filepath)
       
    56                 try:
       
    57                     return (file.read().decode(settings.FILE_CHARSET), filepath)
       
    58                 finally:
       
    59                     file.close()
       
    60             except IOError:
       
    61                 pass
       
    62         raise TemplateDoesNotExist(template_name)
       
    63 
       
    64 _loader = Loader()
       
    65 
       
    66 def load_template_source(template_name, template_dirs=None):
       
    67     # For backwards compatibility
       
    68     import warnings
       
    69     warnings.warn(
       
    70         "'django.template.loaders.app_directories.load_template_source' is deprecated; use 'django.template.loaders.app_directories.Loader' instead.",
       
    71         PendingDeprecationWarning
       
    72     )
       
    73     return _loader.load_template_source(template_name, template_dirs)
       
    74 load_template_source.is_usable = True