A t-string keeps literal fragments separate from evaluated expressions so a renderer can escape text values.
Python template strings: escape text values before rendering HTML
Operation contract
The renderer receives a developer-owned markup template with an invoice ID and a customer note. Literal fragments are preserved; interpolated values are HTML-escaped. The note contains angle brackets and an ampersand, so the output shows them as text rather than treating them as markup.
Failure boundary
This renderer is only for text-node substitutions inside a trusted template. Attribute, URL, CSS, and script contexts need different rules; simply escaping a value does not make an arbitrary HTML template safe. Expression evaluation happens when the t-string is created, before the renderer sees it. Never treat a template object as a general sandbox.
Working program
from html import escape
from string.templatelib import Interpolation
def render_text_nodes(template):
fragments = []
for part in template:
if isinstance(part, Interpolation):
fragments.append(escape(str(part.value), quote=True))
else:
fragments.append(part)
return "".join(fragments)
invoice_id = "inv-47"
customer_note = "<admin>& overdue"
markup = render_text_nodes(t"<p>{invoice_id}: {customer_note}</p>")
print(markup)Output
<p>inv-47: <admin>& overdue</p>Costs and limits
Rendering visits each template fragment and allocates an output string proportional to the final escaped length. It does not parse or validate arbitrary HTML.
Common Mistakes
- A t-string does not escape values automatically.
- Text-node escaping is not an attribute or URL policy.
- Expressions run while constructing the template object.
