Static String

Let’s look at some non-dynamic uses of templating to learn the basics.

Render a String Literal

Let’s start with the simplest form of templating: just a string, no tags, no attributes:

from tdom import html


def main():
    """Main entry point."""
    result = html(t"Hello World")
    return result

We start by importing the html function from tdom. It takes a Python 3.14 t-string and returns a Element with an __str__ that converts to HTML. In this case, the node is an instance of tdom.dom.Text, a subclass of Element.

Simple Render

Same thing, but in a <div>: nothing dynamic, just “template” a string of HTML, but done in one step:

def main():
    """Main entry point."""
    result = html(t"<div>Hello World</div>")
    return result

Show the Element Itself

Let’s take a look at that Element structure. This time, we’ll inspect the node rather than rendering it to a string:

def main():
    """Main entry point."""
    result = html(t'<div class="container">Hello World</div>')
    return result

In our test we see that we got back an Element:

    assert isinstance(result, Element)
    assert result.name == 'div'
    assert result.props == {"class": "container"}
    assert result.children == [{'data': 'Hello World', 'type': 3}]

What does it look like?

  • The result is of type tdom.dom.Element (a subclass of Node)

  • The name of the node (<div>)

  • The properties passed to that tag (in this case, {"class": "container"})

  • The children of this tag (in this case, a Text node of Hello World)

Interpolations as Attribute Values

We can go one step further with this and use interpolations from PEP 750 t-strings. Let’s pass in a Python symbol as part of the template, inside curly braces:

def main():
    """Main entry point."""
    result = html(t'<div class="{f"container{1}"}">Hello World</div>')
    return result

Everything is the same, except the value of the class prop now has a Python int included in the string.

    assert str(main()) == '<div class="container1">Hello World</div>'

If it looks like Python f-strings, well, that’s the point. We did an expression inside that prop value, using a Python expression that evaluated to just the number 1.

Shorthand Syntax

As shorthand, when the entire attribute value is an expression, you can use curly braces instead of putting in double quotes:

def main():
    """Main entry point."""
    result = html(t'<div class={"Container1".lower()}>Hello World</div>')
    return result

Child Nodes in an Element

Let’s look at what more nesting would look like:

def main():
    """Main entry point."""
    structure = html(t"<div>Hello <span>World<em>!</em></span></div>")
    return structure

Over in the test, we see what this looks like:

    assert result.props == {}
    # Test first child
    assert result.children[0] == {'type': 3, 'data': 'Hello '}
    assert str(result) == '<div>Hello <span>World<em>!</em></span></div>'

It’s a nested Python datastructure – pretty simple to look at.

Expressing the Doctype

One last point: the HTML doctype can be a tricky one to get into the template. In tdom this is straightforward:

def main():
    """Main entry point."""
    result = html(t"<!DOCTYPE html><div>Hello World</div>")
    return result

Reducing Boolean Attribute Values

The renderer also knows how to collapse truthy-y values into simplified HTML attributes. Thus, instead of editable="1" you just get the attribute name without a value:

def main():
    """Main entry point."""
    result = html(t"<div editable={True}>Hello World</div>")
    return result

The result is transformed by tdom into a simpler HTML boolean representation:

    assert "<div editable>Hello World</div>" == str(main())