Skip to content

Migrating from docxtpl

Your templates do not change

The tag dialect is reproduced exactly — {{ }}, {%p %}, {%tr %}, {%tc %}, {%r %}, {{r }}, {{p }}, the comment forms, the escaped delimiters, and the colspan / hm / vm / cellbg table directives. Existing .docx templates render unchanged.

Your code does not change either

The package this distribution installs is called docxtpl, so the import line you already have keeps working:

from docxtpl import DocxTemplate, RichText, InlineImage, Subdoc, Listing, R

Only the dependency changes:

-docxtpl>=0.16
+docxtpl-ng>=0.1.0

The two cannot be installed at once — they claim the same import name — so remove the original first. See Installing.

The compatibility classes keep docxtpl's signatures, including the ones the modern API deliberately improves on: render() takes jinja_env positionally and defaults autoescape to off. This surface is supported indefinitely and is not deprecated — if you never want to think about it again, you do not have to.

Then, optionally, move to the modern API

docxtpl modern equivalent
DocxTemplate Template
RichText, R Text
Subdoc Fragment
InlineImage Image
Listing Preformatted
tpl.get_undeclared_template_variables() tpl.undeclared_variables()
tpl.new_subdoc() tpl.new_fragment()
tpl.build_url_id(url) tpl.url_id(url)
tpl.replace_pic() tpl.replace_picture()
tpl.replace_zipname() tpl.replace_zip_member()
tpl.init_docx() tpl.reload()
tpl.get_docx(), tpl.docx tpl.document
tpl.is_saved tpl.has_been_saved
tpl.template_file tpl.source
tpl.allow_missing_pics tpl.allow_missing_replacements
tpl.render_footnotes(), tpl.render_properties() tpl.render_parts(names, context)

The differences beyond the names:

  • render() autoescapes by default. A context value containing & or < no longer produces a document Word refuses to open.
  • jinja_env and autoescape are keyword-only.
  • Everything is annotated, and the package ships py.typed.

pre_processing() and post_processing() are on both surfaces under the same names: save() calls them before and after writing, so a subclass can take a last look at self.document or at the file it produced.

What changes without you asking

Three things behave better than the original, and none of them changes a document that was already correct:

  • a value holding & or < is escaped by Template.render(). With DocxTemplate.render() it is not, matching the original — which stores Ampersand & Angle <> as Ampersand Angle > and loses the characters. This package notices and raises instead of saving text that is not what you passed;
  • a plain string at a {{r }} tag — where the original expects a RichText — is wrapped in a run. The original leaves it as bare text inside a paragraph, which is markup Word offers to repair;
  • empty runs left by a tag that rendered to nothing are removed, where the original keeps them. Word draws both identically.

The parity suite renders the same fixtures through both projects and compares what came out; the differences above are asserted as differences, with the original's own output kept as evidence. See tests/parity/README.md.

Running both at once

You cannot, in one environment: both provide the docxtpl import name. To compare them while migrating, put each in its own environment and compare the documents they produce — which is what this project's parity tests do. See Installing.