jinja2 宏与 jsp2.0 标签

发布于 2024-12-09 09:56:34 字数 1230 浏览 0 评论 0原文

我是一名学习python/jinjajava程序员。

我对 jinja2 宏最大的不满是单个 caller() 的限制。 例如,我可以在 jsp2 标签中执行以下操作:

标签 def:

<% attribute name="title" fragment="true">
<div class='title'>${title}</div>
<div class='body'><jsp:doBody/></div>

用法:

<myTag>
  <jsp:attribute name='title'>
    <c:if test='${blah}'>This is only here sometimes</c:if>
  </jsp:attribute>
  <jsp:body>
    <c:if test='${something}'>some dynamic content</c:if>
  </jsp:body>
</myTag>

我在这里要强调,是正文内容和“标题”属性都具有 内容动态。另外,这里没有将变量设置为动态内容并将它们传递进去的技巧。

现在让我们看一下执行相同操作的 jinja 宏:

{% macro myTag(title='', caller) -%}
  <div class='title'>{{ title }}</div>
  <div class='body'>{{ caller() }}</div>
{%- endmacro %}

但是等等! 我无法轻易将动态内容放入标题属性中!

{% call myTag(title='imagine putting some content here that involves 5 loops, 4 ifs and whatnot?') %}
   {% if something %}some dynamic content{% endif %}
{% endcall %}

这是我新手的问题,还是jinja的缺点?

I am a java programmer learning python/jinja.

My biggest beef with jinja2 macros is the limitation of having a single caller().
for example, i could do the following in jsp2 tags:

tag def:

<% attribute name="title" fragment="true">
<div class='title'>${title}</div>
<div class='body'><jsp:doBody/></div>

usage:

<myTag>
  <jsp:attribute name='title'>
    <c:if test='${blah}'>This is only here sometimes</c:if>
  </jsp:attribute>
  <jsp:body>
    <c:if test='${something}'>some dynamic content</c:if>
  </jsp:body>
</myTag>

what i want to stress here, is that both the body content and the 'title' attribute have content that is dynamic. also, there are no hacks here of setting variables to dynamic content and passing them in.

now lets look at a jinja macro that does the same thing:

{% macro myTag(title='', caller) -%}
  <div class='title'>{{ title }}</div>
  <div class='body'>{{ caller() }}</div>
{%- endmacro %}

but wait! i cannot easily put dynamic content into the title attribute!

{% call myTag(title='imagine putting some content here that involves 5 loops, 4 ifs and whatnot?') %}
   {% if something %}some dynamic content{% endif %}
{% endcall %}

is this a problem with my being a newbie, or is this a shortcoming of jinja?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

醉酒的小男人 2024-12-16 09:56:34

所以事实上这是 Mako Templates for Python 的核心功能。它的使用并不广泛,但对我来说很重要,因为正如您提到的,它在自定义模板标签中非常关键,所以它就在那里:

http://www.makotemplates.org/docs/defs.html#calling-a-def-with-embedded-content-and-or-other-defs

JSP 是其中之一Mako 从中汲取灵感的模板系统。

So in fact this is a core feature of Mako Templates for Python. It's not as widely used of a feature but it's important to me, as it's pretty critical in custom template tags as you mention, so it's there:

http://www.makotemplates.org/docs/defs.html#calling-a-def-with-embedded-content-and-or-other-defs

JSP is one of several template systems Mako draws inspiration from.

≈。彩虹 2024-12-16 09:56:34

除了戴夫建议的 hack 之外,您还可以将本地宏结果传递给任何其他宏。当您事先不知道将传递本地定义的参数还是来自模板变量时,这特别有用:

{% macro doTag(title, body) %}
<div class='title'>{{ title }}</div>
<div class='body'>{{ body }}</div>
{% endmacro %}


{% macro tagBody() %}
{% if something %}some dynamic content{% endif %}
{% endmacro %}

{{ doTag(title='some simple title', body=tagBody() }}

{% macro tagTitle() %}
content here that involves 5 loops, 4 ifs
{% endmacro %}

{{ doTag(title=doTitle(), body=tagBody() }}

In addition to hack suggested by dave you can pass local macro result to any other macro. This is especially useful when you don't know in advance will be passed parameter defined locally or it will come from template variable:

{% macro doTag(title, body) %}
<div class='title'>{{ title }}</div>
<div class='body'>{{ body }}</div>
{% endmacro %}


{% macro tagBody() %}
{% if something %}some dynamic content{% endif %}
{% endmacro %}

{{ doTag(title='some simple title', body=tagBody() }}

{% macro tagTitle() %}
content here that involves 5 loops, 4 ifs
{% endmacro %}

{{ doTag(title=doTitle(), body=tagBody() }}
向地狱狂奔 2024-12-16 09:56:34

所以你是对的,你不能通过多个块。但是,您可以将变量传递回调用方,调用方可以对其进行操作。因此,您可以执行如下操作:

{% macro test() %}
{{ caller('a') }}
{{ caller('b') }}
{% endmacro %}

{% call(which) test() %}
{% if which == 'a' %}hello
{% elif which == 'b' %}world
{% endif %}
{% endcall %}

为了更详细地描述这一点,call(which) 定义了一个采用一个参数 which 的调用者。当宏引用调用者时,它会将其实际希望调用者返回的内容块的标识符传递给调用者。然后调用者可以据此采取行动。

它并不优雅或万无一失,但它确实有效。

So you're right in that you can't pass multiple blocks. However, you can pass a variable back to the caller, which it can act upon. Therefore, you can do something like this:

{% macro test() %}
{{ caller('a') }}
{{ caller('b') }}
{% endmacro %}

{% call(which) test() %}
{% if which == 'a' %}hello
{% elif which == 'b' %}world
{% endif %}
{% endcall %}

To describe that in more detail, call(which) defines a caller that takes one argument, which. When the macro refers to the caller, it passes to the caller an identifier for the block of content it actually wants the caller to return. The caller can then act upon this.

It's not elegant or fool proof, but it works.

世界如花海般美丽 2024-12-16 09:56:34

现在有一个更好的解决方案:

http://mankyd.github.com/jinjatag/

and now there is a better solution:

http://mankyd.github.com/jinjatag/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文