【问题标题】:Delay rendering in jinja2jinja2中的延迟渲染
【发布时间】:2011-12-02 12:39:27
【问题描述】:

我最近从 django 模板转换为 jinja2,到目前为止,我在移植现有模板时没有遇到太多麻烦,但现在我的任务是转换我们的自定义 django 模板标签。我遇到的问题是一个标签,用于创建类似菜单的结构,它看起来像:

{% createmenu mainmenu %}
    <!-- syntax: menuitem url-name-to-resolve <url-args> <url-kwargs> "Url Label" -->
    {% menuitem main-url-name 'Home' %}
    {% menuitem some-other-url-name obj.foo obj.bar 'Page2' %}
    {% if some_condition %}
        {% menuitem some-other-url-name obj.foo obj.bar 'Page2' %}
    {% endif %}
{% menutemplate %}
    <li class="
       {% if menu.is_selected %}selected{% endif %}
       {% if menu.is_first %}first{% endif %}
       {% if menu.is_last %}last{% endif %}">
       {% if menu.is_active %}
           <a href="{{menu.url}}">{{menu.label}}</a>
       {% else %}
           <span class="inactive">{{menu.label}}</span>
       {% endif %}
    </li>
{% endcreatemenu %}

这种行为使得在菜单项上设置类变得更加简单,例如,菜单在渲染时知道它是列表中的第一个还是最后一个,所以如果我在 if 条件下包围一个菜单项,它可能更改它或其他节点是第一个显示还是最后一个显示。

现在到神社。我已经尝试过上下文函数、扩展和宏,但我似乎无法获得相同的行为,因为我不知道如何延迟菜单项的呈现,直到我知道要呈现哪些菜单项。目前我完全不知道如何继续,任何帮助将不胜感激。

【问题讨论】:

  • Jinja 模板调用 Python 函数出了什么问题?什么没用?你遇到了什么问题?
  • 感谢您的回复,并为我的延误感到抱歉。问题是 jinja 在处理它们时会渲染所有节点。所以 AST 看起来像:MENU[ MENUITEM, MENUITEM, IF[ MENUITEM]] 当它被渲染时,我怎么知道第三个或第二个菜单项是最后一个被渲染的?在我的 django 版本中,我做了一些 hacky;我渲染它(不显示)并计算渲染了多少菜单项,然后我再次调用 render 现在知道哪个项目是最后一个。我不确定如何在 jinja 中执行此操作。

标签: django-templates jinja2


【解决方案1】:

只需使用内置loop变量的first和last属性:

{% for item in menu_items %}
<li class="
{%- if loop.first %}first{% endif -%}
{%- if loop.last %}last{% endif -%}">
{# The remainder of your conditions and rendering go here #}
</li>
{% endfor %}

【讨论】:

  • 我曾考虑过类似的事情,不幸的是,第一个/最后一个函数知道菜单项是第一个还是最后一个。可能是菜单列表中的最后一项根本没有呈现,迫使 n-1 项成为最后一个可见项。
  • @Richard - 好吧,我不得不承认现在被难住了 - menu_items 是一个列表还是完全是其他某种数据结构?
  • 它本身并不是一个真正的数据结构。正如我原来的帖子所示,它们是在模板中定义的。
  • @Richard - 所以,为了确保我理解你的正确 - 模板中定义了所有菜单项 - 但根据局部变量的状态,某些元素可能会被隐藏(@987654327 @)?
  • 是的,没错。我开始认为 jinja 无法实现我想要做的事情,话虽如此,我有一个解决方法的想法:- 为列表中的第一个和最后一个预创建两个
  • 。
猜你喜欢
相关资源
最近更新 更多
热门标签