How do I call template defs with names only known at runtime in the Python template language Mako?

StackOverflow https://stackoverflow.com/questions/923837

  •  06-09-2019
  •  | 
  •  

Question

I am trying to find a way of calling def templates determined by the data available in the context.

Edit: A simpler instance of the same question.

It is possible to emit the value of an object in the context:

# in python
ctx = Context(buffer, website='stackoverflow.com')

# in mako
<%def name="body()">
I visit ${website} all the time.
</%def>

Produces:

I visit stackoverflow.com all the time. 

I would like to allow a customization of the output, based upon the data.

# 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>

Changing the format attribute in the context should change the output from

I visit stackoverflow.com all the time.

to

I visit <a href='http://stackoverflow.com'>stackoverflow.com</a> all the time.

The made up syntax I have used in the body def is obviously wrong. What would I need to dynamically specify a template, and then call it?

Was it helpful?

Solution

Takes some playing with mako's local namespace, but here's a working example:

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()

As desired, this emits:

I visit 
<a href='http://stackoverflow.com'>stackoverflow.com</a>
 all the time.

OTHER TIPS

How about if you first generate the template (from another template :), and then run that with your data?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top