1
|
|
|
from django.core.cache import caches, DEFAULT_CACHE_ALIAS |
2
|
|
|
from django.core.cache.utils import make_template_fragment_key |
3
|
|
|
from jinja2.nodes import Keyword, Const, CallBlock |
4
|
|
|
from jinja2.ext import Extension |
5
|
|
|
|
6
|
|
|
from .api import get_last_invalidation |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
class CachalotExtension(Extension): |
10
|
|
|
tags = {'cache'} |
11
|
|
|
allowed_kwargs = ('cache_key', 'timeout', 'cache_alias') |
12
|
|
|
|
13
|
|
|
def __init__(self, environment): |
14
|
|
|
super(CachalotExtension, self).__init__(environment) |
15
|
|
|
|
16
|
|
|
self.environment.globals.update( |
17
|
|
|
get_last_invalidation=get_last_invalidation) |
18
|
|
|
|
19
|
|
|
def parse_args(self, parser): |
20
|
|
|
args = [] |
21
|
|
|
kwargs = [] |
22
|
|
|
|
23
|
|
|
stream = parser.stream |
24
|
|
|
|
25
|
|
|
while stream.current.type != 'block_end': |
26
|
|
|
if stream.current.type == 'name' \ |
27
|
|
|
and stream.look().type == 'assign': |
28
|
|
|
key = stream.current.value |
29
|
|
|
if key not in self.allowed_kwargs: |
30
|
|
|
parser.fail( |
31
|
|
|
"'%s' is not a valid keyword argument " |
32
|
|
|
"for {%% cache %%}" % key, |
33
|
|
|
stream.current.lineno) |
34
|
|
|
stream.skip(2) |
35
|
|
|
value = parser.parse_expression() |
36
|
|
|
kwargs.append(Keyword(key, value, lineno=value.lineno)) |
37
|
|
|
else: |
38
|
|
|
args.append(parser.parse_expression()) |
39
|
|
|
|
40
|
|
|
if stream.current.type == 'block_end': |
41
|
|
|
break |
42
|
|
|
|
43
|
|
|
parser.stream.expect('comma') |
44
|
|
|
|
45
|
|
|
return args, kwargs |
46
|
|
|
|
47
|
|
|
def parse(self, parser): |
48
|
|
|
tag = parser.stream.current.value |
49
|
|
|
lineno = next(parser.stream).lineno |
50
|
|
|
args, kwargs = self.parse_args(parser) |
51
|
|
|
default_cache_key = (None if parser.filename is None |
52
|
|
|
else '%s:%d' % (parser.filename, lineno)) |
53
|
|
|
kwargs.append(Keyword('default_cache_key', Const(default_cache_key), |
54
|
|
|
lineno=lineno)) |
55
|
|
|
body = parser.parse_statements(['name:end' + tag], drop_needle=True) |
56
|
|
|
|
57
|
|
|
return CallBlock(self.call_method('cache', args, kwargs), |
58
|
|
|
[], [], body).set_lineno(lineno) |
59
|
|
|
|
60
|
|
|
def cache(self, *args, **kwargs): |
61
|
|
|
cache_alias = kwargs.get('cache_alias', DEFAULT_CACHE_ALIAS) |
62
|
|
|
cache_key = kwargs.get('cache_key', kwargs['default_cache_key']) |
63
|
|
|
if cache_key is None: |
64
|
|
|
raise ValueError( |
65
|
|
|
'You must set `cache_key` when the template is not a file.') |
66
|
|
|
cache_key = make_template_fragment_key(cache_key, args) |
67
|
|
|
|
68
|
|
|
out = caches[cache_alias].get(cache_key) |
69
|
|
|
if out is None: |
70
|
|
|
out = kwargs['caller']() |
71
|
|
|
caches[cache_alias].set(cache_key, out, kwargs.get('timeout')) |
72
|
|
|
return out |
73
|
|
|
|
74
|
|
|
|
75
|
|
|
ext = CachalotExtension |
76
|
|
|
|