Skip to content

Headers, footers, notes and document properties

A {{ customer.name }} in a page header is just as much a template tag as one in the body. Rendering only the body is the most common bug in this class of library, and this package renders, in this order:

  1. the document body;
  2. every header and footer of every section — six slots each: default, first-page and even-page, header and footer;
  3. footnotes and endnotes;
  4. comments;
  5. the core document properties (docProps/core.xml) — title, subject, author, keywords;
  6. the extended properties (docProps/app.xml) — company, manager;
  7. the custom properties (docProps/custom.xml) — whatever the author named them.

Hyperlink addresses are rendered too, in every one of those parts; see tags in the address.

Nothing is needed to switch this on. One render() call covers all of it, with one context.

from docxtpl import Template

tpl = Template("letter.docx")
tpl.render({"customer": {"name": "Acme GmbH"}, "reference": "2026-0042"})
tpl.save("letter-acme.docx")

Where the same name appears in the body, the header and the document title, it is filled in all three.

Document properties

Type the tag into the property in Word — File → Info, or File → Properties — as you would into the page:

Title: Invoice {{ reference }} for {{ customer.name }}

The properties are XML like everything else, and the tags in them are found the same way. They are worth setting: the title is what a document management system indexes and what Word shows in its recent-files list.

Custom properties

File → Info → Properties → Advanced Properties → Custom is where a document gets a property of its own — Client, Matter, Reviewed. A tag goes in the value:

Name: Client Value: {{ customer.name }}

These are the properties Word's Insert → Quick Parts → Document Property fields and every DOCPROPERTY field code read, so one tag can fill a name that appears on every page.

A property's value carries its type — text, a number, a date, a yes/no. Only the text is rewritten, so a numeric property stays a number.

The field shows the old value until it updates

Inserting a document property puts a field in the document, and a field displays the value cached when it was last computed. Rendering changes the property, not the cache, so the page still shows the old text until the field updates. update_fields() is how you ask for that.

Asking Word to refresh its fields

A table of contents, a page count, a cross-reference and a DOCPROPERTY field all show the value cached when the document was last computed. Rendering changes the document; it does not recompute any of them. So a rendered file carries a table of contents describing the template.

Nothing in this package can compute them — every one depends on how Word lays the document out, which is Word's business. What it can do is ask:

tpl.render(context)
tpl.update_fields()
tpl.save("report-acme.docx")

That sets w:updateFields in word/settings.xml. update_fields(enable=False) removes it again, including from a template that arrived with it, and calling it twice writes one element rather than two.

Like a binary replacement, it is applied when you save() and survives reload() — so it can be set once, outside a loop that renders the same template many times.

Word asks the reader first

On opening the file Word shows "This document contains fields that may refer to other files. Do you want to update this document…?" — and the reader may say no, in which case the table of contents stays stale.

There is no way to make Word update silently. It is not a limitation of this package; the format has no way to express it. LibreOffice updates without asking, so the same document behaves differently in the two.

If the reader must not see a prompt, the table of contents has to be built as ordinary paragraphs — with a fragment — rather than as a field.

Headers linked to the previous section

A section whose header is "linked to previous" has no header of its own — it shows the one before it. Those slots are skipped rather than rendered, and rendering does not create them: a template that went in with one header comes out with one header, not six empty ones.

The order is fixed

Deliberately, and it is part of the interface:

  • an error names the same part on every run, so a failing template is reproducible;
  • relationship ids are allocated in the same order every time, which is what makes two renders of the same template produce byte-identical files.

What is not rendered

Styles, numbering, settings, themes, fonts. A tag in styles.xml is not a template tag; it is a style whose name happens to contain braces.

Text inside a field result. Word caches the last computed value of a field — a page number, a cross-reference — in the document, and the cache is regenerated when the field updates. A tag there would be overwritten by Word.

Anything in a binary part. See replacing images.