【问题标题】:In Jinja2 whats the easiest way to set all the keys to be the values of a dictionary?在 Jinja2 中,将所有键设置为字典值的最简单方法是什么?
【发布时间】:2011-03-22 03:08:20
【问题描述】:

我有一个仪表板,它为每个仪表板项目的上下文命名空间。有没有一种快速的方法可以将字典的所有值设置为模板中的键?

我想重用模板,而不是总是命名我的变量。

我的上下文可以简化为如下所示:

{
 "business": {"businesses": [], "new_promotions": []}, 
 "messages": {"one_to_one": [], "announcements": []
}

因此,在 with 语句中,我想将所有业务项目设置为本地以包含在内。目前,我必须单独设置每个变量:

{% with %}
  {% set businesses = business["businesses"] %}
  {% set new_promotions = business["new_promotions"] %}
  {% include "businesses.html" %}
{% endwith %}

我试过了:

{% with %}
  {% for key, value in my_dict %}
    {% set key = value %}
  {% endfor %}
  {% include "businesses.html" %}
{% endwith %}

但它们仅在 for 循环中具有作用域,因此在包含中没有作用域...

【问题讨论】:

    标签: python templates jinja2


    【解决方案1】:

    长话短说:您不能在上下文中设置任意变量。 {% set key = value %} 只是将名为 key 的变量设置为给定值。

    原因是 Jinja2 将模板编译成 Python 代码。 (如果您想查看模板生成的代码,请在 http://ryshcate.leafstorm.us/paste/71c95831ca0f1d5 下载脚本并将模板的文件名传递给它。)为了加快处理速度,它会为您在模板中使用的每个变量创建局部变量(仅查找第一次遇到上下文中的变量),而不是 Django,它使用上下文进行所有变量查找。

    为了正确生成此代码,它需要能够跟踪在任何给定时间存在哪些局部或全局变量,因此它知道何时在上下文中查找。并且设置随机变量会阻止这个工作,这就是为什么contextfunctions 不允许修改上下文,只是查看它。

    不过,我要做的不是让您的业务显示代码成为一个包含的模板,而是让它成为另一个模板中的宏。例如在businesses.html:

    {% macro show_businesses(businesses, new_promotions) %}
      {# whatever you're displaying... #}
    {% endmacro %}
    

    然后在你的主模板中:

    {% from "businesses.html" import show_businesses %}
    {% show_businesses(**businesses) %}
    

    或者,更好的是,将它们分成两个单独的宏 - 一个用于企业,一个用于新促销。你可以在http://bitbucket.org/plurk/solace/src/tip/solace/templates/看到很多很酷的模板技巧,当然也可以在http://jinja.pocoo.org/2/documentation/templates查看Jinja2文档。

    【讨论】:

    • 感谢 LeafStorm 提供的见解和示例。 business.html 模板确实已经使用了宏,但并非所有仪表板项目都使用宏,但您完全正确,拆分业务逻辑和显示是很好的。在这种情况下,对我来说,我认为最好有一个基于传递的上下文输出模板的上下文函数,因为它意味着更少的模板代码并保持干燥。
    • 为什么我不能做 {% set show['otherdetails'] = true %}
    【解决方案2】:

    我找到了一种解决方法 - 通过创建上下文函数,我可以渲染模板并直接设置上下文或合并上下文(虽然不确定这是一个好习惯)。

    @jinja2.contextfunction
    def render(context, template_name, extra_context, merge=False):
        template = jinja_env.get_template(template_name)
    
        # Merge or standalone context?
        if merge:
            ctx = context.items()
            ctx.update(extra_context)
        else:
            ctx = extra_context
    
        return jinja2.Markup(template.render(ctx))
    

    所以我的模板看起来像:

    {{ render("businesses.html", business) }}
    

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2011-04-24
      • 2011-01-23
      • 1970-01-01
      相关资源
      最近更新 更多