You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
55 lines
2.0 KiB
55 lines
2.0 KiB
from jinja2 import nodes
|
|
from jinja2.ext import Extension
|
|
|
|
|
|
class FragmentCacheExtension(Extension):
|
|
# a set of names that trigger the extension.
|
|
tags = {"cache"}
|
|
|
|
def __init__(self, environment):
|
|
super().__init__(environment)
|
|
|
|
# add the defaults to the environment
|
|
environment.extend(fragment_cache_prefix="", fragment_cache=None)
|
|
|
|
def parse(self, parser):
|
|
# the first token is the token that started the tag. In our case
|
|
# we only listen to ``'cache'`` so this will be a name token with
|
|
# `cache` as value. We get the line number so that we can give
|
|
# that line number to the nodes we create by hand.
|
|
lineno = next(parser.stream).lineno
|
|
|
|
# now we parse a single expression that is used as cache key.
|
|
args = [parser.parse_expression()]
|
|
|
|
# if there is a comma, the user provided a timeout. If not use
|
|
# None as second parameter.
|
|
if parser.stream.skip_if("comma"):
|
|
args.append(parser.parse_expression())
|
|
else:
|
|
args.append(nodes.Const(None))
|
|
|
|
# now we parse the body of the cache block up to `endcache` and
|
|
# drop the needle (which would always be `endcache` in that case)
|
|
body = parser.parse_statements(["name:endcache"], drop_needle=True)
|
|
|
|
# now return a `CallBlock` node that calls our _cache_support
|
|
# helper method on this extension.
|
|
return nodes.CallBlock(
|
|
self.call_method("_cache_support", args), [], [], body
|
|
).set_lineno(lineno)
|
|
|
|
def _cache_support(self, name, timeout, caller):
|
|
"""Helper callback."""
|
|
key = self.environment.fragment_cache_prefix + name
|
|
|
|
# try to load the block from the cache
|
|
# if there is no fragment in the cache, render it and store
|
|
# it in the cache.
|
|
rv = self.environment.fragment_cache.get(key)
|
|
if rv is not None:
|
|
return rv
|
|
rv = caller()
|
|
self.environment.fragment_cache.add(key, rv, timeout)
|
|
return rv
|