Home

Partials with chameleon templates

Updated:
Created:

There has been a discussion about partials in the context of the fabulous htmx. The question was how do you return only small pieces of html on dynamic requests, which might be just subsections of a larger page.

Michael Kennedy has published chameleon partials. This allows writing small pieces of html templates using the chameleon template language, and either returning the rendered html directly or using it in a page.

My approach would be the other way around: use metal macros. This is an “old” and well tested feature of the template language. You mark a section of a larger page as a macro, and then you can reuse this macro somewhere else on the page, or in another template file. With a small extra template one could also render the macro directly (one could possibly render the macro directly, but this needs to be researched another time).

The files

templates/test1.pt

This file contains macro1, the template snippet that is to be reused

<div>
Some other text
<div metal:define-macro="macro1">
    Hello <span tal:content="name">Replace this with name</span>!
</div>
</div>

templates/test2.pt

This is the other page, which uses macro1 as a normal metal macro.

<div>
This is test2
<span metal:use-macro="templates['test1'].macros.macro1"></span>
</div>

test.py

The test script showing how everything plays together.

import os
from chameleon import PageTemplateLoader, PageTemplate

templates = PageTemplateLoader(os.path.join(os.path.dirname(__file__), 'templates'), '.pt')

get_partial=PageTemplate('<span metal:use-macro="templates[file_name].macros[macro_name]"></span>')

# Render the macro only
as_partial = get_partial(
    templates=templates,
    file_name='test1',
    macro_name='macro1',
    name='world')
print(as_partial)

print('\n------------------\n')

# Use the macro within another page
as_macro = templates['test2'](templates=templates,
                              name='world2')
print(as_macro)

The trick is obviously the get_partial PageTemplate, which is used to render a macro macro_name in the file file_name.

The output

<div>
    Hello <span>world</span>!
</div>

------------------

<div>
This is test2
<div>
    Hello <span>world2</span>!
</div>
</div>

This approach might be easier to use compared to an extra library, and might also feel more natural for users of TAL / chameleon.