2012-05-17 5 views
7

Ich versuche, so etwas zu tun:Wie kann ich indirekt ein Makro in einer Jinja2-Vorlage aufrufen?

{% macro obj_type_1 %} 
stuff 
{% endmacro %} 
{% macro obj_type_2 %} 
stuff 
{% endmacro %} 

{{ (obj|get_type)(obj) }} 

In diesem Beispiel get_type ein Filter, die obj_type_1 oder obj_type_2 zurückkehren würde - dh der Name des Makros rufen für obj. Ich möchte nicht obj mit Konfigurationsausgabe markieren, weil gerade obj in mehreren Vorlagen als Strukturdaten verwendet wird, mit unterschiedlichen Markup je nach Kontext gerendert werden.

Ich weiß, die Syntax hier ist ein bisschen gequält, aber ich denke, das ist, weil das, was ich tun möchte, nicht sofort in Jinja Vorlagen möglich ist. Ich versuche, einen großen Schwalbe von if/elif/else Mist in einigen Config Generation Code mit Vorlagen zu ersetzen, aber dieses Bit scheint ein Knackpunkt zu sein.

+0

Sie sind also im Grunde eine Art und Weise zu 'eval()' in Jinja2 suchen? – Blender

+0

In der Nähe von; Ich möchte ein Makro namentlich aufrufen. –

Antwort

0

Persönlich, da get_type als Dispatcher verwendet wird, wäre es transparenter, es als jinja-Makro zu implementieren, das ein spezialisiertes Makro aufruft, das auf dem Typ von obj basiert. Dies macht es überflüssig, ein aufrufbares Makro zurückzugeben und konsolidiert gleichzeitig die spezialisierten Makros und die Logik, die angibt, wie/wann sie verwendet werden.

8

Sie können einen Jinja2-Filter erstellen, der das Makro aus dem aktuellen Kontext bezieht und dann das Makro auswertet. Der Filter ist:

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

Wenn Ihre Anwendung erfordert, können Sie String-Manipulation auf macro_name vor Nachschlagen in der Makro in context.vars auszuführen. Hier

ist ein vollständiges Beispiel:

#!/usr/bin/env python 
from jinja2 import Environment, contextfilter 

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

template_string = """\ 
{%- macro MyMacro(item) %}MyMacro({{ item }}){% endmacro -%} 
{{ MyMacro('direct') }} 
{{ 'MyMacro' | macro('indirect') }} 
""" 

env = Environment() 
env.filters['macro'] = call_macro_by_name 
template = env.from_string(template_string) 
print(template.render()) 

die

druckt
MyMacro(direct) 
MyMacro(indirect) 
2

Makros einfach durch Import dict Nutzung genannt werden:

macros.html

{% macro render_foo(value) %} 
HELLO {{ value }}! 
{% endmacro %} 
my_view.html 210

{% import "macros.html" as my_macros %} 

{% set macro_name = 'render_' + dynamic_content %} 
{{ my_macros[macro_name]('world') }} 

machen, wie:

HELLO world! 
Verwandte Themen