Eu tenho um aplicativo Django SaaS com usuários que criam seus próprios modelos Jinja2 (em um ambiente extraordinariamente seguro, para aqueles que apenas se encolheram), que são salvos em um banco de dados. eu tenho um template_type
campo, observando se um determinado modelo é um "incluir" ou um "modelo completo" (um modelo completo pode incluir "inclui"). O problema é que um usuário poderia colocar {% include "foo" %}
em um modelo chamado "bar"
e {% include "bar" %}
no "foo"
modelo, causando um RuntimeError: maximum recursion depth exceeded
tipo de situação, o que não seria bom para o desempenho.
Existe uma maneira legal de lidar com essa situação que não inclui um regexp de validação (por exemplo, r"{%s+include"
) verifique se há inclusões durante o tempo de criação do modelo do usuário ("Certifique-se de que uma importação recursiva nunca fique no banco de dados, ou seu servidor irá asplode" não combina comigo).
Minha tentativa falhada
Eu comecei usando um carregador personalizado que contém apenas um usuário "s" inclui "::
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)
O problema em fazer isso é que eu basicamente me impedi de tirar proveito do Jinja2. Cache de Bytecode, o que claramente exigiria que todos os modelos estivessem disponíveis para um load(...
chamada, que por sua vez chama get_source(...
.
Respostas:
3 para resposta № 1Para analisar modelos e verificar inclui, eu uso este código:
ast = env.parse(template_text)
for each in meta.find_referenced_templates(ast) : # find the (% includes %}