htmltmpl: templating engine for separation of code and HTML

This is the Python version of htmltmpl. This page contains some basic information about the module and examples that illustrate its usage.

A complete documentation of the module's API can be found here. It contains description of all public classes and methods which the module provides. The documentation is automatically generated from docstrings in source file of the module by my application easydoc, which uses htmltmpl and is included in the htmltmpl distribution.

The module should work on all platforms supported by Python. The module is supported by its author only on the UNIX platform using Python versions 2.1 or newer.

Releases 1.15 and up are vastly redesigned to be multi-task safe and more flexible. The design and interface was completely changed to be much more object oriented and more maintainable. The downside of this change is that the interface is no longer similar to that of HTML::Template.

The module is multi-task safe in terms of properly synchronized accesses to the precompiled templates that are loaded from and saved to disk. However, instances of any of its classes should NOT be shared by multiple threads. The only exception are instances of the Template class, which can be shared by multiple threads.

It would be possible to protect all critical data and sections by locks to achieve complete thread safeness, but the resulting overhead probably is not worth the effort. I hardly can imagine a situation in which someone would want or need to share the instances among multiple threads.


Examples

Source files of all these examples are available in 'doc/examples' directory of the distribution. Files from the regression test suite (the 'test' directory) can also serve as examples.

FAQ: Emacs (the 'htmlize-file' command) is used to colorify the source code examples.

simple:

template.tmpl

<html>
    <head>
        <title><TMPL_VAR title></title>
    </head>
    <body>
        <h1>Customers:</h1>
        <p>
            Total: <TMPL_VAR Customers> 
        </p>

        ### this comment will be removed

        <table>
            <TMPL_LOOP Customers>
                <tr>
                    <TMPL_IF new>
                        <td>new customer</td> 
                    <TMPL_ELSE>
                        <td>old customer</td>
                    </TMPL_IF>
                    <td><TMPL_VAR __PASS__></td>
                    <td><TMPL_VAR name></td>
                    <td><TMPL_VAR city></td>
                </tr>
            </TMPL_LOOP>
        </table>
    </body>
</html>
    

template.py

from htmltmpl import TemplateManager, TemplateProcessor

# Compile or load already precompiled template.
template = TemplateManager().prepare("template.tmpl")
tproc = TemplateProcessor()

# Set the title.
tproc.set("title", "Our customers")

# Create the 'Customers' loop.
customers = []

# First customer.
customer = {}
customer["name"] = "Joe Sixpack"
customer["city"] = "Los Angeles"
customer["new"] = 0
customers.append(customer)

# Second customer.
customer = {}
customer["name"] = "Paul Newman"
customer["city"] = "New York"
customer["new"] = 1
customers.append(customer)

tproc.set("Customers", customers)

# Print the processed template.
print tproc.process(template)
    

template.html

<html>
    <head>
        <title>Our customers</title>
    </head>
    <body>
        <h1>Customers:</h1>
        <p>
            Total: 2
        </p>



        <table>
            <tr>
                    <td>old customer</td>
                <td>1</td>
                <td>Joe Sixpack</td>
                <td>Los Angeles</td>
            </tr>
            <tr>
                    <td>new customer</td>
                <td>2</td>
                <td>Paul Newman</td>
                <td>New York</td>
            </tr>                
        </table>
    </body>
</html>
    

MySQL driven:

products.tmpl

<html>
    <head>
        <title><TMPL_VAR title></title>
    </head>
    <body>

    <h1>Our products</h1>

    <table>
        <TMPL_LOOP Products>
            <tr>
                <td><TMPL_VAR id></td>
                <td><TMPL_VAR name></td>
            </tr>
        </TMPL_LOOP>
    </table>

    </body>
</html>
    

products.py

import MySQLdb
import MySQLdb.cursors
from htmltmpl import TemplateManager, TemplateProcessor

# Define some constants.
DB = "test"
USER = ""
PASSWD = ""
TABLE = """

    CREATE TABLE IF NOT EXISTS Products (
        id            INTEGER        NOT NULL AUTO_INCREMENT,
        name          VARCHAR(255)   NOT NULL,
        CONSTRAINT pkey_id
            PRIMARY KEY(id)
    )
    
"""

template = TemplateManager().prepare("products.tmpl")
tproc = TemplateProcessor()
                
# Assign a string to template variable named "title".
tproc.set("title", "Our products")
        
# Connect the database. Create the table.
db = MySQLdb.connect(db = DB, user = USER, passwd = PASSWD,
                     cursorclass = MySQLdb.cursors.DictCursor)
create_cur = db.cursor()
create_cur.execute(TABLE)
create_cur.close()

# Insert some data.
insert_cur = db.cursor()
insert_cur.executemany("""

    INSERT INTO Products (name) VALUES (%(name)s)

""", [
    {"name": "Seagate"},
    {"name": "Conner"},
    {"name": "Maxtor"}
])
insert_cur.close()


# Select the products.
products_cur = db.cursor()
products_cur.execute("""

    SELECT id, name
    FROM Products
    
""")

# Append product data in form of mappings (dictionaries) to the
# products list.
products = []
for i in range(products_cur.rowcount):
    products.append(products_cur.fetchone())
products_cur.close()
db.close()

# Assign the products list to template loop identifier 'Products'.
# NOTE: htmltmpl automatically converts all the values
# to strings using str().
tproc.set("Products", products)
        
# Process the template and print the result.
print tproc.process(template)
    

products.html

<html>
    <head>
        <title>Our products</title>
    </head>
    <body>

        <h1>Our products</h1>

        <table>
                <tr>
                    <td>1</td>
                    <td>Seagate</td>
                </tr>
                <tr>
                    <td>2</td>
                    <td>Conner</td>
                </tr>
                <tr>
                    <td>3</td>
                    <td>Maxtor</td>
                </tr>
        </table>

    </body>
</html>