|
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
|
|
|
|