|
38
|
1 |
""" |
|
|
2 |
Wrapper class that takes a list of template loaders as an argument and attempts |
|
|
3 |
to load templates from them in order, caching the result. |
|
|
4 |
""" |
|
|
5 |
|
|
|
6 |
from django.core.exceptions import ImproperlyConfigured |
|
|
7 |
from django.template import TemplateDoesNotExist |
|
|
8 |
from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin |
|
|
9 |
from django.utils.hashcompat import sha_constructor |
|
|
10 |
from django.utils.importlib import import_module |
|
|
11 |
|
|
|
12 |
class Loader(BaseLoader): |
|
|
13 |
is_usable = True |
|
|
14 |
|
|
|
15 |
def __init__(self, loaders): |
|
|
16 |
self.template_cache = {} |
|
|
17 |
self._loaders = loaders |
|
|
18 |
self._cached_loaders = [] |
|
|
19 |
|
|
|
20 |
@property |
|
|
21 |
def loaders(self): |
|
|
22 |
# Resolve loaders on demand to avoid circular imports |
|
|
23 |
if not self._cached_loaders: |
|
|
24 |
for loader in self._loaders: |
|
|
25 |
self._cached_loaders.append(find_template_loader(loader)) |
|
|
26 |
return self._cached_loaders |
|
|
27 |
|
|
|
28 |
def find_template(self, name, dirs=None): |
|
|
29 |
for loader in self.loaders: |
|
|
30 |
try: |
|
|
31 |
template, display_name = loader(name, dirs) |
|
|
32 |
return (template, make_origin(display_name, loader, name, dirs)) |
|
|
33 |
except TemplateDoesNotExist: |
|
|
34 |
pass |
|
|
35 |
raise TemplateDoesNotExist(name) |
|
|
36 |
|
|
|
37 |
def load_template(self, template_name, template_dirs=None): |
|
|
38 |
key = template_name |
|
|
39 |
if template_dirs: |
|
|
40 |
# If template directories were specified, use a hash to differentiate |
|
|
41 |
key = '-'.join([template_name, sha_constructor('|'.join(template_dirs)).hexdigest()]) |
|
|
42 |
|
|
|
43 |
if key not in self.template_cache: |
|
|
44 |
template, origin = self.find_template(template_name, template_dirs) |
|
|
45 |
if not hasattr(template, 'render'): |
|
|
46 |
try: |
|
|
47 |
template = get_template_from_string(template, origin, template_name) |
|
|
48 |
except TemplateDoesNotExist: |
|
|
49 |
# If compiling the template we found raises TemplateDoesNotExist, |
|
|
50 |
# back off to returning the source and display name for the template |
|
|
51 |
# we were asked to load. This allows for correct identification (later) |
|
|
52 |
# of the actual template that does not exist. |
|
|
53 |
return template, origin |
|
|
54 |
self.template_cache[key] = template |
|
|
55 |
return self.template_cache[key], None |
|
|
56 |
|
|
|
57 |
def reset(self): |
|
|
58 |
"Empty the template cache." |
|
|
59 |
self.template_cache.clear() |