7

私が行っている名前付きタプルのリストがあり、それぞれレンダリング要件がわずかに異なるため、属性に基づいて適切なマクロを呼び出したいと考えています。私が持っているのはこれです:

{% macro format_item(item) %}
    {% if item.type_of == 'a' %}
        {{ format_a(item) }}
    {% elif item.type_of == 'b' %}
        {{ format_b(item) }}
    {% elif item.type_of == 'c'%}
        {{ format_c(item) }}
    {% elif item.type_of == 'd'%}
        {{ format_d(item) }}
    {% else %}
        {{ format_general(item) }}
    {% endif %}
{% endmacro %}

しかし、私が欲しいのは次のようなものです:

...iterating through list of items
{{ call macro based off item.type_of }}

この時点で、通常のpythonで次のようにします

getattr(object_with_method_to_produce_templates, item)

しかし、 attr フィルターを効果的に使用する方法を見つけていません (この状況で適切に使用できる場合)。

興味深いかもしれない他の場所を探しているフラスコを見つけました(代わりに、事前にすべて実行して、事前に計算され、事前にフォーマットされたアイテムをテンプレートに送信できる場合)。多分やりすぎて、現時点でやりたいことを超えています。

将来かなり大きくなる可能性のある if then のリストの代わりに、さまざまなマクロのリストから呼び出すより良い方法は何ですか? よくある質問のように思えますが、私が探している正確な答えにつまずいたわけではありません。

編集:

これを私がしていたことに追加し、レンダリングしたいアイテムの一部として呼び出し可能なマクロを生成しようとしました

from flask import get_template_attribute
from jinja2 import Template
test_template = Template('{% macro test_macro(item) %}<div id="test-div">sent to me: {{ item }}</div>{% endmacro %}')

...アイテム生成中...

 template = get_template_attribute(test_template, 'test_macro')

...テンプレートで...アイテムを繰り返し、各アイテムに対して

{{ item.template("testing this method") }}

これは機能しますが、通常のマクロではなく、文字列文字のみを生成します (つまり、div は div としてレンダリングされず、テキストとしてのみレンダリングされます)。

<div id="test-div">sent to me: testing this method</div>

したがって、テンプレートに何らかのコンテキストを与える必要があります。または、これが目指していたものに近いが正しくないように思われるものを与える必要があります。

EDIT2:

{{ item.template("testing this method")|safe }}

私が探していたものを返すので、これはまずまずです。私が持っていたnamedtupleの配置をバイパスして、マクロを渡すことができるかもしれません...もっと取り組んでいると思います。これは最適/好ましいですか、それとも混乱ですか?

4

1 に答える 1

6

現在のコンテキストからマクロを取得し、マクロを評価する Jinja2 フィルターを作成できます。フィルターは次のとおりです。

@contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
    return context.vars[macro_name](*args, **kwargs)

ここで完全な回答を参照してください。

于 2014-07-03T12:16:38.823 に答える