Article
· May 29 4m read

Use Mako Python template engine to generate dynamic content

Template engines are essential for producing customizable dynamic content, without the need for compilation and opening up great possibilities of extensibility for the template user. Especially if the template engine supports Python. A popular solution for template engine is Mko. It is is a template library written in Python. It provides a familiar, non-XML syntax which compiles into Python modules for maximum performance. Mako's syntax and API borrows from the best ideas of many others, including Django and Jinja2 templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded Python (i.e. Python Server Page) language, which refines the familiar ideas of componentized layout and inheritance to produce one of the most straightforward and flexible models available, while also maintaining close ties to Python calling and scoping semantics. Mako is used by reddit.com where it delivers over one billion page views per month. It is the default template language included with the Pylons and Pyramid web frameworks (source: https://www.makotemplates.org/).

Simple sample with Mako

This code snippet demonstrates the power of Mako in generating dynamic content with full Python support:

<%inherit file="base.html"/>
<%
    rows = [[v for v in range(0,10)] for row in range(0,10)]
%>
<table>
    % for row in rows:
        ${makerow(row)}
    % endfor
</table>
<%def name="makerow(row)">
    <tr>
    % for name in row:
        <td>${name}</td>\
    % endfor
    </tr>
</%def>

Mako statements:

Statement <% ... %> Executes Python code; used for logic, loops, conditionals, etc.
Block (for loops, if) <% if condition: %> / <% for item in items: %> Starts a control block; must be closed properly.
End of Block <% end %> or dedent in Python Marks the end of a control block (depending on syntax).
Include Statement <%include file="filename" /> Includes another template or file.
Call Function <%call expr()%> Calls a block or macro defined in the template.
Macro Definition <%def name(args): %> Defines a macro that can be reused.
Macro Call <%call name(args)%> Calls a macro defined with <%def %>.

 

Using Mako templates with IRIS

I developed an IRIS application that uses Mako, the health-gforms open exchange package (https://openexchange.intersystems.com/package/health-gforms). For this application, the Mako was used to generate a valid FHIR JSON message to create a new patient on server:

{
    "resourceType": "Patient",
    "name": [
        {
            "use": "official",
            "given": [
                "${data['name']}"
            ],
            "family": "${data['family']}"
        }
    ],
    "gender": "${data['gender']}",
    "birthDate": "${data['birthDate']}",
    "telecom": [
        {
            "value": "${data['telecom']}",
            "use": "mobile",
            "system": "phone"
        }
    ]
}

The Mako will receive a data object with patient given and family names, gender, birth date and telecom contact. Mako get the values to apply to final content using ${} instruction.

When the template is rendered the result is:

{
    "resourceType": "Patient",
    "name": [
        {
            "use": "official",
            "given": [
                "Jack"
            ],
            "family": "Chain"
        }
    ],
    "gender": "male",
    "birthDate": "1956-01-01",
    "telecom": [
        {
            "value": "555-555-555",
            "use": "mobile",
            "system": "phone"
        }
    ]
}

The IRIS Embeddded Python code to render the template is:

from mako.template import Template

...

for data in records:
        if getattr(data, "title") == "Given Name":
            makodata["name"] = getattr(data,"userResponse")
        elif getattr(data, "title") == "Family Name":
            makodata["family"] = getattr(data,"userResponse")
        elif getattr(data, "title") == "Gender":
            makodata["gender"] = getattr(data,"userResponse")
        elif getattr(data, "title") == "Birth Date":
            makodata["birthDate"] = getattr(data,"userResponse")
        elif getattr(data, "title") == "Phone":
            makodata["telecom"] = getattr(data,"userResponse")

template = Template(filename=templatepath)

return template.render(data=makodata)

1. A Template instance is created with filename to the template file.

2. The template.render receives makodata on data variable and render the content using it.

Discussion (2)2
Log in or sign up to continue