Составить подраздел Jinja2 AST - PullRequest
2 голосов
/ 30 ноября 2010

Можно ли скомпилировать или восстановить часть Jinja2 AST?

Например, можно ли вызвать функцию или метод из jinja2.environment или jinja2.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 после включения
  2. Вставьте javascript вверху, включая файл в Jinja 2

Спасибо за чтение.

Брайан

1 Ответ

1 голос
/ 30 ноября 2010

Компиляция в unicode пока невозможна в методе parse(), поскольку у вас нет контекста, доступного в этот момент. Вы можете взломать его, конечно, но это, вероятно, не лучший путь.

Обратите внимание, что шаг 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 %}. После этого обязательно удалите его, или он появится в вашем шаблоне.

...