我有一个 Django SaaS 应用程序,用户创建了自己的 Jinja2 模板(在一个非常沙盒环境中,对于那些只是畏缩的人),这些模板保存到数据库中。我有一个template_type
字段,指出给定模板是“包含”还是“完整模板”(完整模板当然可以包含“包含”)。问题是用户可以将{% include "foo" %}
一个名为"bar"
的模板{% include "bar" %}
放入"foo"
模板中,从而导致一种RuntimeError: maximum recursion depth exceeded
不利于性能的情况。
有没有一种很好的方法来处理这种情况,它不包括验证正则表达式(例如,r'\{%\s+include'
)在用户模板创建期间检查包含(“确保递归导入永远不会进入数据库,否则你的服务器将崩溃”不'不太喜欢我)。
我失败的尝试
我首先使用了一个自定义加载器,它只包含用户的“包含”::
def get_source(self, environment, template):
"""
Returns the source of the template or raises ``TemplateNotFound``.
This loader is for use with an environment which intends to load each
template from a string, since only includes are loaded from here.
"""
try:
template = self.snippets[template]
except KeyError:
raise jinja2.TemplateNotFound(
template, message=u'Snippet "{s}" was not found'.format(s=template)
)
else:
source = template['source']
return (source, None, lambda: True)
这样做的问题是我基本上阻止了自己利用 Jinja2 的Bytecode Cache,这显然要求所有模板都可用于load(...
调用,而调用get_source(...
.