如何在Jinja上下文功能中设置(非全球)变量



我想设置变量值,但仅在尚未分配和在本地上下文中时。

因此,有一个解决方案:

{% with x=( x | default(1)) %}
    {{ x }}
{% endwith %}
{% with x=2 %}
    {% with x=( x | default(1)) %}
        {{ x }}
    {% endwith %}
{% endwith %}

这很好地工作了,但这是很多文本。我有很多情况,我只有一个,但最多有20个变量正在设置,然后称为宏,或将这些值随附一个模板。

编写所有这些默认条件只是一团糟,并且会引起错误。因此,我很想能够在当前上下文中设定价值。在上下文功能中。但是,如果我尝试以下操作:

@contextfunction
def defaults(ctx, **vals):
    for k,v in vals.iteritems():
      if k not in ctx:
          ctx[k] = v

我得到一个例外:

typeError:'上下文'对象不支持项目分配

试图在ctx.vars上设置值也不会有帮助:

vars
模板本地变量。此列表包含来自父范围以及本地的环境和上下文功能 来自模板的修改和导出变量。模板 将在模板评估期间修改此命令,但过滤器和 上下文功能不允许修改它。
http://jinja.pocoo.org/docs/2.9/api/#jinja2.context.vars

我尝试了

@contextfunction
def defaults(ctx, **vals):
    for k,v in vals.iteritems():
         if k not in ctx.vars:
             ctx.vars[k] = v

也没有例外,但似乎只是没有将值分配给上下文。

我知道我可以写入全球环境,但这不是我想做的,因为它会产生副作用。

是否有可能仅获得当前上下文并为其设置价值?我没有找到任何说明,以及如何做到这一点,我并没有真正掌握阅读Jinja来源的那样。

我找到了一个解决方案,不知何故我一直在解决自己的问题。这并不是对问题的答案:"我如何在jinja上下文功能中设置(非全球)变量?" ,但它解决了问题。

我写了一个jinja扩展名,它允许一个简单的"默认"标签:

from jinja2 import nodes
from jinja2.ext import Extension
"""
    DefaultExtension
    ~~~~~~~~~~~~~~~~
    Very simple jinja extension that allows for the following 
    {% set x=(x | default(1)) %}
    {% set y=(y | default(2)) %}
    to be written as 
    {% default x=1, y=2 %}
    :copyright: (c) 2017 by the Roman Seidl
    :license: BSD
"""
class DefaultExtension(Extension):
    # a set of names that trigger the extension.
    tags = set(['default'])
    def parse(self, parser):
        #just dump the tag
        lineno = next(parser.stream).lineno
        #parse through assignments (similar to parser.parse_with)
        assignments = []
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if assignments:
                parser.stream.expect('comma')
            target = parser.parse_assign_target()
            parser.stream.expect('assign')
            expr = (parser.parse_expression())
            #consruct a 'default' filter
            filter = nodes.Filter(nodes.Name(target.name, 'load'), 'default', [expr], [], None, None, lineno=lineno)
            #produce an assignment with this filter as value
            assignment = nodes.Assign(target, filter, lineno=lineno)
            assignments.append(assignment)
      return assignments

我只需要将其添加到我的应用中:

app.jinja_env.add_extension(DefaultExtension)

它的效果很好,尽管我必须承认我尚未对其进行彻底的测试。

有人认为我应该将其提交给Jinja?

最新更新