2017-09-04 21 views
0

我想设置变量值,但只有当它们尚未分配并且在本地上下文中时。如何在jinja上下文函数中设置(非全局)变量?

所以有此一解决方案:

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

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

这工作得很好,但它是一个大量的文字。我有很多情况下我没有一个,但最多可以设置20个变量,然后调用一个宏,或者包含这些值的模板。

写所有这些默认条件只是乱七八糟,会引发错误。因此,我希望能够为例如当前的上下文设置一个值。在上下文功能中。但是,如果我尝试以下方法:

​​

我得到一个异常:

TypeError: 'Context' object does not support item assignment

,并试图设置ctx.vars值将没有帮助:

vars
The template local variables. This list contains environment and context functions from the parent scope as well as local modifications and exported variables from the template. The template will modify this dict during template evaluation but filters and context functions are not allowed to modify it.
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的来源掌握。

回答

0

我发现了一个解决方案,不知何故我一直在解决自己的问题。这不是对这个问题的完全回答“我如何在一个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?