首页 文章

如何在jinja上下文函数中设置(非全局)变量?

提问于
浏览
0

我想设置变量值,但仅限于它们尚未分配且位于本地上下文中 .

所以有一个解决方案:

{% 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:'Context'对象不支持项目分配

并尝试在ctx.vars上设置一个值也无济于事:

vars模板局部变量 . 此列表包含父作用域中的环境和上下文函数以及模板中的本地修改和导出变量 . 模板将在模板评估期间修改此dict,但不允许过滤器和上下文功能对其进行修改 . 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来源 .

1 回答

  • 0

    我找到了一个解决方案,不知怎的,我一直在解决自己的问题 . 这不是"How can I set a (non-global) variable in a jinja context function?"问题的答案,但它解决了这个问题 .

    我写了一个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吗?

相关问题