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 | > import hashlib
|
---|
7 | > from django.template.base import TemplateDoesNotExist
|
---|
8 | > from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
|
---|
9 | > from django.utils.encoding import force_bytes
|
---|
10 |
|
---|
11 | > class Loader(BaseLoader):
|
---|
12 | > is_usable = True
|
---|
13 |
|
---|
14 | > def __init__(self, loaders):
|
---|
15 | > self.template_cache = {}
|
---|
16 | > self.find_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 | # Set self._cached_loaders atomically. Otherwise, another thread
|
---|
25 | # could see an incomplete list. See #17303.
|
---|
26 | ! cached_loaders = []
|
---|
27 | ! for loader in self._loaders:
|
---|
28 | ! cached_loaders.append(find_template_loader(loader))
|
---|
29 | ! self._cached_loaders = cached_loaders
|
---|
30 | > return self._cached_loaders
|
---|
31 |
|
---|
32 | > def cache_key(self, template_name, template_dirs):
|
---|
33 | > if template_dirs:
|
---|
34 | # If template directories were specified, use a hash to differentiate
|
---|
35 | ! return '-'.join([template_name, hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()])
|
---|
36 | > else:
|
---|
37 | > return template_name
|
---|
38 |
|
---|
39 | > def find_template(self, name, dirs=None):
|
---|
40 | > key = self.cache_key(name, dirs)
|
---|
41 | > try:
|
---|
42 | > res = self.find_template_cache[key]
|
---|
43 | > except KeyError:
|
---|
44 | > res = None
|
---|
45 | > for loader in self.loaders:
|
---|
46 | > try:
|
---|
47 | > template, display_name = loader(name, dirs)
|
---|
48 | > res = (template, make_origin(display_name, loader, name, dirs))
|
---|
49 | > except TemplateDoesNotExist:
|
---|
50 | > pass
|
---|
51 | > self.find_template_cache[key] = res
|
---|
52 | > if res:
|
---|
53 | > return res
|
---|
54 | > else:
|
---|
55 | > raise TemplateDoesNotExist(name)
|
---|
56 |
|
---|
57 | > def load_template(self, template_name, template_dirs=None):
|
---|
58 | > key = self.cache_key(template_name, template_dirs)
|
---|
59 | > try:
|
---|
60 | > template = self.template_cache[key]
|
---|
61 | > except KeyError:
|
---|
62 | > template, origin = self.find_template(template_name, template_dirs)
|
---|
63 | > if not hasattr(template, 'render'):
|
---|
64 | > try:
|
---|
65 | > template = get_template_from_string(template, origin, template_name)
|
---|
66 | > except TemplateDoesNotExist:
|
---|
67 | # If compiling the template we found raises TemplateDoesNotExist,
|
---|
68 | # back off to returning the source and display name for the template
|
---|
69 | # we were asked to load. This allows for correct identification (later)
|
---|
70 | # of the actual template that does not exist.
|
---|
71 | > return template, origin
|
---|
72 | > self.template_cache[key] = template
|
---|
73 | > return template, None
|
---|
74 |
|
---|
75 | > def reset(self):
|
---|
76 | > "Empty the template cache."
|
---|
77 | > self.template_cache.clear()
|
---|
78 | > self.find_template_cache.clear()
|
---|