Como faço para chamar defs modelo com nomes conhecidos apenas em tempo de execução no modelo de linguagem Python Mako?
Pergunta
Eu estou tentando encontrar uma maneira de chamar def moldes determinados pelos dados disponíveis no contexto.
Editar: Um exemplo simples da mesma pergunta.
É possível emitir o valor de um objeto no contexto:
# in python
ctx = Context(buffer, website='stackoverflow.com')
# in mako
<%def name="body()">
I visit ${website} all the time.
</%def>
Produz:
I visit stackoverflow.com all the time.
Eu gostaria de permitir uma personalização da saída, com base nos dados.
# in python
ctx = Context(buffer, website='stackoverflow.com', format='text')
# in mako
<%def name="body()">
I visit ${(format + '_link')(website)} all the time. <-- Made up syntax.
</%def>
<%def name='html_link(w)'>
<a href='http://${w}'>${w}</a>
</%def>
<%def name='text_link(w)'>
${w}
</%def>
A alteração do atributo format
no contexto deve mudar a saída do
I visit stackoverflow.com all the time.
para
I visit <a href='http://stackoverflow.com'>stackoverflow.com</a> all the time.
O composta sintaxe Eu tenho usado no body
def
está obviamente errado. O que eu preciso especificar dinamicamente um modelo e, em seguida, chamá-lo?
Solução
Toma algum jogo com namespace local
de mako, mas aqui está um exemplo de trabalho:
from mako.template import Template
from mako.runtime import Context
from StringIO import StringIO
mytemplate = Template("""
<%def name='html_link(w)'>
<a href='http://${w}'>${w}</a>
</%def>
<%def name='text_link(w)'>
${w}
</%def>
<%def name="body()">
I visit ${getattr(local, format + '_link')(website)} all the time.
</%def>
""")
buf = StringIO()
ctx = Context(buf, website='stackoverflow.com', format='html')
mytemplate.render_context(ctx)
print buf.getvalue()
Como desejado, Emite:
I visit
<a href='http://stackoverflow.com'>stackoverflow.com</a>
all the time.
Outras dicas
E se você primeiro gerar o modelo (de outro modelo :), e depois executar isso com seus dados?