首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jinja2:在模板中呈现模板

Jinja2:在模板中呈现模板
EN

Stack Overflow用户
提问于 2016-10-19 13:01:50
回答 3查看 8.8K关注 0票数 8

是否可以在由字符串提供的另一个模板中呈现Jinja2模板?例如,我想要字符串

代码语言:javascript
复制
{{ s1 }}

将呈现给

代码语言:javascript
复制
Hello world

将下面的字典作为Template.render的param

代码语言:javascript
复制
{ 's1': 'Hello {{ s2 }}', 's2': 'world' }

我知道类似的过程可以通过include标记将s1的内容分离到另一个文件来完成,但是这里我不想这样做。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-29 14:46:07

我没有一个很容易测试这些想法的环境,但我正在探索类似于气流使用jinja模板的东西。

从我所能找到的最佳方法来看,这是在外部模板中显式地呈现内部模板字符串。为此,您可能需要在param字典中传递或导入模板构造函数

下面是一些(未经测试的)代码:

代码语言:javascript
复制
from jinja2 import Template
template_string = '{{ Template(s1).render(s2=s2) }}'
outer_template = Template(template_string)
outer_template.render( 
    s1='Hello {{ s2 }}', 
    s2='world',
    Template=Template
)

这一点并不像您所希望的那样干净,所以我们可以通过创建一个自定义过滤器来更进一步,这样我们就可以这样使用它了:

代码语言:javascript
复制
{{ s1|inner_render({"s2":s2}) }}

下面是一个自定义过滤器,我认为它可以完成这个任务:

代码语言:javascript
复制
from jinja2 import Template
def inner_render(value, context):
    return Template(value).render(context)

现在让我们假设我们想要与外部模板相同的上下文,以及--到底是什么--让我们呈现任意数量的深度级别,N。希望一些示例用法将类似于:

代码语言:javascript
复制
{{ s1|recursive_render }}

{{ s3|recursive_render(2) }}

从自定义过滤器获取上下文的一种简单方法是使用contextfilter装饰器

代码语言:javascript
复制
from jinja2 import Template
from jinja2 import contextfilter
@contextfilter
def recursive_render(context, value, N=1):
    if N == 1:
        val_to_render = value
    else:
        val_to_render = recursive_render(context, value, N-1)
    return Template(value).render(context)

现在您可以做一些类似s3 = '{{ s1 }}!!!'{{ s3|recursive_render(2) }}应该呈现给Hello world!!!的事情了。我想您可以更进一步,通过计数括号来检测要呈现多少级别。

在经历了所有这些之后,我想明确地指出,,这是非常令人困惑的

虽然我认为我已经发现在我非常具体的气流使用中需要2级渲染,但我无法想象还需要更多的水平。

如果你正在阅读“这正是我所需要的”的想法:无论你想做什么,都可以做得更有说服力。退一步,考虑一下您可能有一个xy问题,并重新阅读jinja的文档,以确保没有更好的方法。

票数 8
EN

Stack Overflow用户

发布于 2021-06-11 10:02:26

那么,您可以始终创建一个过滤器,如:

代码语言:javascript
复制
@app.template_filter('t')
def trenderiza(value, obj):
  rtemplate = Environment(loader=BaseLoader()).from_string(value)
  return rtemplate.render(**obj)

所以如果

代码语言:javascript
复制
s1="Hello {{s2}}"

您可以从模板中筛选如下:

代码语言:javascript
复制
 <p>{{s1|t(dict(s2='world')}}</p>
票数 0
EN

Stack Overflow用户

发布于 2021-07-21 19:49:50

您可以使用低级别的Jinja,从Ansible核心偷来的。

代码语言:javascript
复制
#!/usr/bin/env python3

# Stolen from Ansible, thus licensed under GPLv3+.

from collections.abc import Mapping
from jinja2 import Template

# https://github.com/ansible/ansible/blob/13c28664ae0817068386b893858f4f6daa702052/lib/ansible/template/vars.py#L33
class CustomVars(Mapping):
    '''
    Helper class to template all variable content before jinja2 sees it. This is
    done by hijacking the variable storage that jinja2 uses, and overriding __contains__
    and __getitem__ to look like a dict.
    '''

    def __init__(self, templar, data):
        self._data = data
        self._templar = templar

    def __contains__(self, k):
        return k in self._data

    def __iter__(self):
        keys = set()
        keys.update(self._data)
        return iter(keys)

    def __len__(self):
        keys = set()
        keys.update(self._data)
        return len(keys)

    def __getitem__(self, varname):
        variable = self._data[varname]
        return self._templar.template(variable)

# https://github.com/ansible/ansible/blob/13c28664ae0817068386b893858f4f6daa702052/lib/ansible/template/__init__.py#L661
class Templar:

    def __init__(self, data):

        self._data = data

    def template(self, variable):

        '''
        Assume string for now.
        TODO: add isinstance checks for sequence, mapping.
        '''

        t = Template(variable)
        ctx = t.new_context(CustomVars(self, self._data), shared=True) # shared=True is important, not quite sure yet, why.
        rf = t.root_render_func(ctx)

        return "".join(rf)

t_str = "{{ s1 }}"
data = { 's1': 'Hello {{ s2 }}', 's2': 'world' }

t = Templar(data)
print("template result: %s" % t.template(t_str))
代码语言:javascript
复制
template result: Hello world
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40132165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档