Compile subsection of Jinja2 AST

自古美人都是妖i 提交于 2019-12-12 21:05:16

问题


Can one compile or revert a portion of the Jinja2 AST?

For example, is it possible to call a function or method from jinja2.environment or jinja2.compiler.generate or some equivalent on a list of nodes extracted from within a template?

For example, given a template y.html:

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

and an extension 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()

Running python y.py results in the expected output of:

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

In the parse method, how can one either:

  1. compile body to unicode (i.e. tag-content 8); or, alternatively
  2. revert body to its original source (i.e. tag-content {{ 3 + 5 }}).

As a matter of background, this question relates to two prior questions:

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

Thank you for reading.

Brian


回答1:


Compiling to unicode is not yet possible in the parse() method since you don't have the context available at that point. You can hack around it ofcourse but it would probably not be the best way to go.

Note that the parse() step is normally only executed once on a html file, after that it will use the parsed bytecode to render the template. The results of the parse step can be rendered given an environment.

You simply don't have the context available there, and getting the context in there... quite difficult ;)

To get the original source however... not much easier without hacking, but the hacking isn't too bad ;)

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

After that you can read the text as the value from the {% raw %} node. Be sure to trash it after that or it will show in your template.



来源:https://stackoverflow.com/questions/4309266/compile-subsection-of-jinja2-ast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!