django1/django/template/loaders/cached.py

80 lines
3.1 KiB
Python

"""
Wrapper class that takes a list of template loaders as an argument and attempts
to load templates from them in order, caching the result.
"""
import hashlib
from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
from django.utils.encoding import force_bytes
class Loader(BaseLoader):
is_usable = True
def __init__(self, loaders):
self.template_cache = {}
self.find_template_cache = {}
self._loaders = loaders
self._cached_loaders = []
@property
def loaders(self):
# Resolve loaders on demand to avoid circular imports
if not self._cached_loaders:
# Set self._cached_loaders atomically. Otherwise, another thread
# could see an incomplete list. See #17303.
cached_loaders = []
for loader in self._loaders:
cached_loaders.append(find_template_loader(loader))
self._cached_loaders = cached_loaders
return self._cached_loaders
def cache_key(self, template_name, template_dirs):
if template_dirs:
# If template directories were specified, use a hash to differentiate
return '-'.join([template_name, hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()])
else:
return template_name
def find_template(self, name, dirs=None):
key = self.cache_key(name, dirs)
try:
result = self.find_template_cache[key]
except KeyError:
result = None
for loader in self.loaders:
try:
template, display_name = loader(name, dirs)
except TemplateDoesNotExist:
pass
else:
result = (template, make_origin(display_name, loader, name, dirs))
self.find_template_cache[key] = result
if result:
return result
else:
raise TemplateDoesNotExist(name)
def load_template(self, template_name, template_dirs=None):
key = self.cache_key(template_name, template_dirs)
try:
template = self.template_cache[key]
except KeyError:
template, origin = self.find_template(template_name, template_dirs)
if not hasattr(template, 'render'):
try:
template = get_template_from_string(template, origin, template_name)
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 template, origin
self.template_cache[key] = template
return template, None
def reset(self):
"Empty the template cache."
self.template_cache.clear()
self.find_template_cache.clear()