2012-12-24 14 views
7

Ich habe eine Liste von namedtuples, die ich durchlaufe, die sich leicht in den Renderinganforderungen unterscheiden, also möchte ich das richtige Makro basierend auf einem Attribut aufrufen. Was ich habe, ist dies:jinja2: Makro Auswählen von Makro- oder dynamischen Makroaufrufen

{% 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 %} 

aber was ich will, ist so etwas wie:

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

an dieser Stelle in regelmäßigen Python ich etwas tun würde, wie

getattr(object_with_method_to_produce_templates, item) 

aber haven Ich habe einen Weg gefunden, den Attrfilter effektiv zu benutzen (wenn ich ihn in dieser Situation überhaupt richtig benutzen kann).

Ich habe flask.get_template_attribute gefunden woanders, was interessant sein könnte (wenn ich stattdessen einfach alles im Voraus tun und ein vorberechnetes und vorformatiertes Element an die Vorlage senden kann). Vielleicht zu viel und darüber hinaus, was ich in dieser Zeit machen möchte.

Was ist eine bessere Möglichkeit, aus einer vielfältigen Auflistung von Makros anstelle einer Liste von Wenns zu rufen, die in der Zukunft ziemlich groß werden könnte? Scheint wie eine allgemeine Frage, aber ich bin nicht über die genaue Antwort gestolpert, nach der ich suche.

EDIT:

Ich habe diese zu dem, was ich tat und versuchte, eine aufrufbare Makro zu erzeugen, als Teil des Artikel I

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 %}') 

... in Artikel Generation machen möchten ...

template = get_template_attribute(test_template, 'test_macro') 

... in Vorlage ... iterieren Artikel dann für jedes Element

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

welche Art von funktioniert aber nur den String Buchstaben für den Buchstaben generiert, nicht als ein reguläres Makro würde (d. H. Die Divs werden nicht als divs dargestellt, nur als Text.

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

Also ich brauche Vorlage etwas Kontext zu geben, oder etwas das ist näher an, was für strebe aber scheint nicht richtig.

EDIT2:

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

kehrt, was ich gesucht habe, so ist dies befahrbar, ich könnte in der Lage sein, die namedtuple Anordnung zu umgehen ich hatte, und übergeben Sie einfach ein Makro mit ... mehr daran zu arbeiten I annehmen. Ist das optimal/vorzuziehen oder ein Durcheinander?

+0

Werfen Sie einen Blick auf HTML-Escaping in den Jinja-Dokumenten und dem sicheren Filter. – voscausa

+0

Ok, ich habe sie mir angesehen, aber nicht die genaue Verbindung hergestellt, die ich machen muss.Ich denke, ich habe ein Makro als einen Block von Code erstellt, aber nicht als HTML markiert (wie eine Dateiendung anzeigt), so dass das Makro nur als reiner Text neu nummeriert wird, hmmm, lasst uns das ein bisschen herumstochern . – blueblank

Antwort

5

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) 

Die gesamte Antwort here.