【问题标题】:Compile subsection of Jinja2 ASTJinja2 AST 的编译小节
【发布时间】:2010-11-29 23:49:42
【问题描述】:

可以编译或还原 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 }})。

作为背景问题,这个问题与之前的两个问题有关:

  1. Jinja2 compile extension after includes;和
  2. Insert javascript at top of including file in Jinja 2

感谢您的阅读。

布赖恩

【问题讨论】:

    标签: python jinja2 abstract-syntax-tree


    【解决方案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
    

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

    【讨论】:

    • 感谢 WoLpH。我认为这回答了我的问题。我认为,唯一剩下的问题是,是否有办法在给定环境的情况下呈现提取的结果。
    • @Brian M. Hunt:这没问题,因为您可以以任何一种方式呈现任何字符串。您可以将Environment.from_string()Template(nodes) 与您通常返回的任何内容一起使用。
    • 哦,对了!抱歉,我不清楚......我认为唯一的剩余问题是,是否有办法在给定环境的情况下呈现提取的 nodes(不是文本)。
    • @Brian M. Hunt:Template(nodes).render() 不会为你这样做吗?如果不是我可能会误解你。
    • @WoLpH:我之前也想过,但它给了我一个RuntimeError: maximum recursion depth exceeded 错误。
    猜你喜欢
    • 2021-12-20
    • 2016-07-15
    • 2020-07-26
    • 2020-11-14
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    相关资源
    最近更新 更多