10. Notes

Questions about HTML templates

What types of markup does HTMLTemplate accept?

HTML - as long as elements are closed as-per XML/XHTML standards - and XHTML are both supported. XML templating is possible, but limited by Python's HTMLParser module to lowercase tag and attribute names; see the doc/ISSUES file.

Can HTMLTemplate be used for non-markup based templating?

It can, though it isn't designed for it; use texttemplate module instead.

Does HTMLTemplate modify a template's original HTML markup at all?

Slightly: all tag attributes will be double- or single-quoted (a side-effect of using Python's HTMLParser module to parse the template).

Do HTML templates need to be complete HTML documents with a single root element, or can HTMLTemplate handle arbitrary fragments of HTML too?

Both are fine. HTMLTemplate doesn't require a template be a complete HTML document, nor even that it has a single root element as some templating engines may do.

Does HTMLTemplate support caching and/or pickling of compiled templates?

No. The template parser is very fast and templates generally only need to be compiled once as Template objects are reusable, so no caching system is necessary.

Can HTMLTemplate use id attributes or namespace-based attributes to indicate template nodes, e.g. for compatibility with WYSIWYG HTML editors?

Yes, you can specify an alternate attribute name via the Template constructor; for example: Template(callback, html, attribute='id') or Template(callback, html, attribute='tpl:node'). If using an existing HTML attributes such as id, note that only id attributes containing compiler directives will be removed by HTMLTemplate; other id attributes will conveniently be left intact.

How does HTMLTemplate fit into the popular MVC (Model-View-Controller) application design pattern?

HTMLTemplate's design is strongly influenced by the MVC pattern commonly used in desktop application design, where the Controller is a bridge between Model and View. (Note this is Apple Computer's popular definition of the MVC pattern, as opposed to the original PARC/Smalltalk definition.) A directive-tagged HTML template and Python control code corresponds closely to the View and Controller layers of this pattern: the HTMLTemplate compiler performs a similar role to Apple's Interface Builder in constructing the View layer as a live object model, while the Python control code that manipulates this object model at rendering time forms the Controller layer.

Questions about manipulating Template object models

Is it possible to modify just part of an element's content; for example, replacing only the 'XXXX' part of <title>Hello XXXX</title>?

Yes. There's at least a couple of ways this can be done:

Can the Repeater class's repeat method only iterate over lists, or can it work with any kind of iterable object?

Any object that supports iteration is fine.

I'd like to use a Repeater without having to create a list of values to iterate over first. Is this possible?

Yes. If you know in advance how many times you want to repeat it, just use Python's built-in xrange function; for example: node.foo.repeat(callback, xrange(n), *args). If you don't know, or want to stop repeating from within the callback function, this can be done as follows:

class FakeIterator:
    """Fake iterable object; passes itself as each 'item'. 
       Call its stop() method to stop iteration.
    """
    def __init__(self):
        self._stop = False
    
    def stop(self):
        self._stop = True
    
    def __iter__(self):
        return self
    
    def next(self):
        if self._stop: 
            raise StopIteration
        else:
            return self


    def renderFoo(node, *args):
        node.bar.repeat(renderBar, FakeIterator(), *args)
	
    def renderBar(node, item, *args):
        ...
        if shouldStop: 
            item.stop()

I'd like to render a table with alternately coloured rows. How can I do this?

Quite easily. See the sample/Demo5_AlternatingRowColors.py script for a sample solution.

I'd like to render a large number of pages, all sharing the same navigation bar. For efficiency, I'd like to render this navigation bar only once rather than re-generating it for every page. Is this possible?

Yes. There are various ways to do this:

How can I dynamically add HTML comments/directives/processing instructions to a rendered page?

HTMLTemplate doesn't support these HTML constructs as first-class nodes as this is rarely useful, but the relevant markup can be inserted easily enough via placeholder elements such as <div node="-con:mycomment"></div> using code like: node.mycomment.raw = '<!-- %s -->' % commentstr. Remember to perform any necessary validation on the content being inserted yourself (e.g. checking that commentstr doesn't contain '--', which is invalid within a comment according to HTML/SGML rules).