编译Jinja2 AST的子部分

时间:2010-11-29 23:49:43

标签: python jinja2 abstract-syntax-tree

可以编译或还原部分Jinja2 AST吗?

例如,是否可以从jinja2.environmentjinja2.compiler.generate调用函数或方法,或从模板中提取的节点列表中调用某些函数或方法?

例如,给定模板y.html

avant-tag
{% xyz %}
tag content {{ 3 + 5 }}
{% endxyz %}
apres-tag

和扩展程序y.py

# -*- coding: utf-8 -*-
from jinja2 import nodes, Environment, FileSystemLoader
from jinja2.ext import Extension

class YExtension(Extension):
    tags = set(['y'])

    def __init__(self, environment):
        super(YExtension, self).__init__(environment)

    def parse(self, parser):
        tag = parser.stream.next()
        body = parser.parse_statements(['name:endy'], drop_needle=True)
        return nodes.Const("<!-- slurping: %s -->" % str(body))

env = Environment(
    loader      = FileSystemLoader('.'),
    extensions  = [YExtension],
    )

print env.get_template('x.html').render()

运行python y.py会产生预期的输出:

avant-tag
 <!-- slurping: [Output(nodes=[TemplateData(data=u'\n    tag-content '),
   Add(left=Const(value=3), right=Const(value=5)),
   TemplateData(data=u'\n ')])] -->
sous-tag

parse方法中,如何:

  1. body编译为unicode(即tag-content 8);或者,或者
  2. body还原为其原始来源(即tag-content {{ 3 + 5 }})。
  3. 作为背景问题,这个问题涉及两个先前的问题:

    1. Jinja2 compile extension after includes;和
    2. Insert javascript at top of including file in Jinja 2
    3. 感谢您的阅读。

      布赖恩

1 个答案:

答案 0 :(得分:1)

parse()方法中尚无法编译为unicode,因为此时您没有可用的上下文。你可以在它周围进行攻击,但它可能不是最好的方法。

请注意,parse()步骤通常只在html文件上执行一次,之后它将使用解析的字节码来呈现模板。在给定环境的情况下,可以呈现解析步骤的结果。

你根本就没有上下文,并且在那里获得上下文......非常困难;)

要获得原始资源但是如果没有黑客攻击就不会那么容易,但是黑客攻击并不是太糟糕;)

class YExtension(Extension):
    tags = set(['y'])

    def preprocess(self, source, name, filename=None):
        # insert some code here that replaces '{% xyz %}foo bar{% endxyz %}'
        # with something like: '{% xyz %}foo bar{% raw %}foo bar{% endraw %}{% endxyz %}'
        return source

之后,您可以从value节点读取文本{% raw %}。请务必在此之后将其删除,否则它会显示在您的模板中。