67

我有以下 Jinja 模板:

{% set mybool = False %}
{% for thing in things %}
    <div class='indent1'>
        <ul>
            {% if current_user %}
              {% if current_user.username == thing['created_by']['username'] %}
                {% set mybool = True %}
                <li>mybool: {{ mybool }}</li> <!-- prints True -->
                <li><a href='#'>Edit</a></li>
              {% endif %}
            {% endif %}
            <li>Flag</li>
        </ul>
    </div>
    <hr />
{% endfor %}

{% if not mybool %}
    <!-- always prints this -->
    <p>mybool is false!</p>
{% else %}
  <p>mybool is true!</p>
{% endif %}

如果在for循环中满足条件,我想更改mybool为 true 以便我可以mybool is true!在下面显示。但是,看起来内部的范围mybool仅限于if语句,因此永远不会设置期望。 mybool

如何设置“全局”mybool以便在最后一条if语句中使用它?

编辑

我找到了一些建议(只有正确的缓存页面视图),但它们似乎不起作用。也许它们在 Jinja2 中已被弃用...

编辑

下面提供的解决方案。我仍然很好奇为什么上面的建议不起作用。有谁知道他们被弃用了?

4

8 回答 8

53

解决此限制的一种方法是启用“do”表达式语句扩展并使用数组而不是布尔值:

{% set exists = [] %}
{% for i in range(5) %}
      {% if True %}
          {% do exists.append(1) %}
      {% endif %}
{% endfor %}
{% if exists %}
    <!-- exists is true -->
{% endif %}

要启用 Jinja 的“do”表达式语句扩展:e = jinja2.Environment(extensions=["jinja2.ext.do",])

于 2011-02-02T22:00:57.320 回答
17

对相关问题的回答:我希望有一个全局计数器来记录我在模板中输入某个 if 块的次数,结果如下。

在模板的顶部:

{% set counter = ['1'] %}

在 if 块中,我想计算:

{% if counter.append('1') %}{% endif %}

显示计数时:

{{ counter|length }}

我相信该字符串'1'可以替换为任何字符串或数字。它仍然是一个 hack,但不是很大。

于 2014-03-06T18:56:37.430 回答
13

2018 年更新

从 Jinja 2.10(2017 年 11 月 8 日)开始,有一个namespace()对象可以解决这个特殊问题。有关更多详细信息和示例,请参阅官方作业文档;然后class文档说明了如何将多个值分配给命名空间。

于 2018-05-13T02:08:33.483 回答
8

您可以使用此 hack 解决您的问题(无需扩展):

import jinja2

env = jinja2.Environment()
print env.from_string("""
{% set mybool = [False] %}
{% for thing in things %}
    <div class='indent1'>
        <ul>
            {% if current_user %}
              {% if current_user.username == thing['created_by']['username'] %}
                {% set _ = mybool.append(not mybool.pop()) %}
                <li>mybool: {{ mybool[0] }}</li> <!-- prints True -->
                <li><a href='#'>Edit</a></li>
              {% endif %}
            {% endif %}
            <li>Flag</li>
        </ul>
    </div>
    <hr />
{% endfor %}

{% if not mybool[0] %}
    <!-- always prints this -->
    <p>mybool is false!</p>
{% else %}
  <p>mybool is true!</p>
{% endif %}
""").render(current_user={'username':'me'},things=[{'created_by':{'username':'me'}},{'created_by':{'username':'you'}}])
于 2014-02-18T16:57:29.120 回答
8

这是任何想要使用该对象在循环namespace()外保持变量的人的一般情况。for

{% set accumulator = namespace(total=0) %}
{% for i in range(0,3) %}
    {% set accumulator.total = i + accumulator.total %}
    {{accumulator.total}}
 {% endfor %}`          {# 0 1 3 #}
 {{accumulator.total}}  {# 3 (accumulator.total persisted past the end of the loop) #}
于 2019-09-07T16:27:57.123 回答
4

在编写 acontextfunction()或类似内容时,您可能已经注意到上下文试图阻止您对其进行修改。

如果您已设法使用内部上下文 API 修改上下文,您可能已经注意到上下文中的更改似乎在模板中不可见。这样做的原因是Jinja出于性能原因,仅将上下文用作模板变量的主要数据源。

如果要修改上下文,请编写一个返回变量的函数,而不是使用 set 将其分配给变量:

{% set comments = get_latest_comments() %}

来源

于 2011-10-05T12:53:04.740 回答
3

需要从列表 (objects_from_db) 中找到对象 (object) 中的最大条目数,

由于 jinja2 和变量范围中已知的原因,这不起作用。

 {% set maxlength = 0 %}
 {% for object in objects_from_db %}
     {% set ilen = object.entries | length %}
     {% if maxlength < ilen %}
         {% set maxlength = ilen %}
     {% endif %}
 {% endfor %}

这是有效的:

 {% set mlength = [0]%}
 {% for object in objects_from_db %}
     {% set ilen = object.entries | length %}
     {% if mlength[0] < ilen %}
         {% set _ = mlength.pop() %}
         {% set _ = mlength.append(ilen)%}
     {% endif %}
 {% endfor %}
 {% set maxlength = mlength[0] %}

希望这可以帮助其他人试图弄清楚同样的事情。

于 2017-03-19T15:22:56.387 回答
0

发现这篇描述小技巧的好文章。无法在不同范围内更改 jinja 变量的值,但可以修改全局字典值:

# works because dictionary pointer cannot change, but entries can 

{% set users = ['alice','bob','eve'] %} 
{% set foundUser = { 'flag': False } %} 

initial-check-on-global-foundUser: 
  cmd.run: 
    name: echo initial foundUser = {{foundUser.flag}} 

{% for user in users %} 
{%- if user == "bob" %} 
{%-   if foundUser.update({'flag':True}) %}{%- endif %} 
{%- endif %} 
echo-for-{{user}}: 
  cmd.run: 
    name: echo my name is {{user}}, has bob been found? {{foundUser.flag}} 
{% endfor %} 

final-check-on-global-foundUser: 
  cmd.run: 
    name: echo final foundUser = {{foundUser.flag}}

我还发现这种语法在不实际使用的情况下设置值非常有用set

{%-   if foundUser.update({'flag':True}) %}{%- endif %} 

它实际上检查update字典上的操作结果(自我注释)。

于 2018-08-29T13:35:45.537 回答