Quickstart¶
1. Write the template in Word¶
Create the document as you want it to look. Where a value goes, type a tag:
Dear
{{ customer.name }},Your order of
{{ order.date }}totalling{{ total }}has shipped.
Formatting applies to tags as it does to any other text — make the tag bold and the rendered value is bold.
2. Render it¶
from docxtpl import Template
tpl = Template("letter.docx")
tpl.render({
"customer": {"name": "Acme GmbH"},
"order": {"date": "2026-08-04"},
"total": "€1,240.00",
})
tpl.save("letter-acme.docx")
3. Repeat a table row¶
Prefix the loop tags with tr so that the row is what repeats rather than the
text. A prefixed tag removes the element it names, so the two tags go in
rows of their own, above and below the row that repeats — a {%tr for %} in the
repeating row would take that row's content with it.
| Item | Qty | Price |
|---|---|---|
{%tr for line in lines %} |
||
{{ line.name }} |
{{ line.qty }} |
{{ line.price }} |
{%tr endfor %} |
The two tag rows never appear in the rendered document. See Template syntax for the rest of the dialect, and Tables for merging and shading cells.
4. Render the same template many times¶
Rendering mutates the document, so a second render() applies to the first
render's output. To run one template over many contexts, reload between them:
tpl = Template("letter.docx")
for customer in customers:
tpl.reload()
tpl.render({"customer": customer})
tpl.save(f"letter-{customer.id}.docx")
is_rendered says whether a render has happened, if you would rather check than
reload. In the compatibility API the same method is init_docx().
5. From the command line¶
For build pipelines, and the fastest way to reproduce a problem: