jinja2中的延迟渲染

Posted

技术标签:

【中文标题】jinja2中的延迟渲染【英文标题】:Delay rendering in jinja2 【发布时间】: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 中执行此操作。 【参考方案1】:

只需使用内置loop变量的firstlast属性:

% 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 无法实现我想要做的事情,话虽如此,我有一个解决方法的想法:- 为列表中的第一个和最后一个预创建两个 。

以上是关于jinja2中的延迟渲染的主要内容,如果未能解决你的问题,请参考以下文章

使用 jinja2 模板引擎渲染 django 表单

渲染 Jinja2 宏而不影响模板其余部分的内容

为啥这个 Jinja2 模板的渲染速度不比 Django 快?

Jinja2:说“在另一个宏或模板中渲染这个宏”

flask 渲染jinja2模版和传参

Unity的延迟渲染(一)