2017-09-04 56 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?