python-docx 库的核心功能是程序化创建全新的 Word 文档,但在基于已有模板替换其部分内容时,其操作会非常繁琐。用户需要先解析文档结构、定位具体位置、手动替换内容,并维护原有格式与布局,导致开发效率较低。
python-docx-template 正是为解决这一痛点而设计的。它借鉴 Jinja2 模板引擎的思路,允许在 Word 文档中直接插入类似 {{variable}} 的占位符,随后仅用几行代码即可完成数据填充,无需关心底层文档结构,完美适配基于模板修改文档的场景。

python-docx-template 基于 python-docx 实现文档读写功能,并借助 jinja2 提供灵活的模板标签支持,其设计思路如下:
- 用 Word 制作模板 在 Microsoft Word 中自由设计文档格式,如插入图片、设置页眉页脚、调整表格样式,充分利用 Word 强大的排版功能。
- 插入模板变量
在需要动态内容的位置,直接输入 Jinja2 风格的标签,例如
{{company_name}}或{%for item in list%}。 - 保存为模板文件 将文档保存为普通的.docx 文件,该文件即成为可复用的模板。
- 用 Python 批量生成 加载模板并传入字典或对象,python-docx-template 会自动替换标签,生成最终文档。
python-docx-template 的官方代码仓库地址为:python-docx-template,详细文档可参阅:python-docx-template doc。本文使用的 python-docx-template 版本为 0.20.2,安装命令如下:
pip install docxtpl
其中,docxtpl 是 python-docx-template 库的正式分发名称,二者指代同一工具。
1 使用说明
1.1 核心概念
1.1.1 标签说明
python-docx-template 允许在 Word 文档中使用 Jinja2 标签和过滤器。但为确保其在 Word 中正常运作,需遵循若干限制。
常规 Jinja2 标签仅能在同一段落内且同一文本运行中使用,若需控制段落、表格行或包含样式的完整文本运行,则必须使用后续章节介绍的复杂元素标签语法。
举例而言,若创建一个所有字符样式相同的段落,Word 内部只会生成一个文本运行对象。但若在该段落中将部分文字设置为加粗,Word 会将原有文本运行拆分为三个独立部分,分别对应普通样式、加粗样式及恢复后的普通样式。
标签
若要对段落、表格行、表格列以及文本段进行管理,需使用以下专用语法:
- 段落标签:
{%p jinja2_tag %} - 表格行标签:
{%tr jinja2_tag %} - 表格列标签:
{%tc jinja2_tag %} - 文本段标签:
{%r jinja2_tag %}
这些以{% %}包裹的内容是 Jinja2 模板语法标签,引擎会识别并执行其中的逻辑。一个完整的模板标签基本结构如下:
{% 指令关键字 参数/条件 %} // 起始标签 内容 // 被标签控制的文本 {% 结束关键字 %} // 结束标签
通过此类标签,python-docx-template 可自动将标准 Jinja2 标签,即去除前缀 p、tr、tc、r 后的内容,精确嵌入到文档 XML 源码的相应位置。

假设模板内容如下:
{%p if display_paragraph %} 一段或多段文本内容 {%p endif %}
无论 display_paragraph 变量取值如何,首尾两个包含{%p ... %}标签的段落,都不会出现在最终生成的 docx 文档中。
只有当 display_paragraph 的值为 True 时,以下内容才会被保留在生成的文档里:
一段或多段文本内容
对于模板里的标签格式需遵循如下要求,否则无法生成正确结果:
-
起始标签分隔符后必须加空格,结束标签分隔符前必须加空格:
-
同一段落、行、列或文本段内,禁止连续使用标签分隔符:
-
标签与内容不可写在同一行,需换行排版:
正确示例:
{%p if display_paragraph %} Here is my paragraph {%p endif %}
错误示例:
{%p if display_paragraph %}Here is my paragraph {%p endif %}
错误示例:
{%p{%tr{%tc{%r
正确示例:
{% if something %} {%p if display_paragraph %}
错误示例:
{%if something%} {%pif display_paragraph%}
1.1.2 常见元素
显示变量
Jinja2 模板里,可以用双大括号来显示变量:
{{ <变量名> }}
如果变量是普通字符串,字符串里的特殊符号会自动转换成对应的格式:
→ 换行→ 分段→ 制表符(按一下 Tab 键的效果)→ 分页符
如果变量是富文本(RichText)对象,必须在变量名前加一个 r,明确表示要渲染这个富文本内容:
{{r <变量名> }}
注意,r 要紧跟在左大括号的后面。
此外,变量名中禁止直接使用 <,>, & 这类字符,除非用了转义语法。
注释
可以在模板中添加类 Jinja2 风格的注释,注释不会被渲染到最终文件:
{#p 这是一个段落类型的注释 #} {#tr 这是一个表格行类型的注释 #} {#tc 这是一个单元格类型的注释 #}
在执行如下代码对模板文件进行渲染操作时,模板中原有的所有注释信息均会被清除,不会保留在最终的渲染结果中:
from docxtpl import DocxTemplate
import os
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/comments_tpl.docx
tpl = DocxTemplate("templates/comments_tpl.docx")
tpl.render({})
os.makedirs("output", exist_ok=True)
tpl.save("output/comments.docx")
文本的拆分与合并
若包含 Jinja2 标签的文本过长,会导致可读性下降,例如:
我的房子位于{% if living_in_town %}城市区域{% else %}乡村地区{% endif %},我非常喜欢它。
借助{-语法,可将 Jinja2 标签与上一行内容合并,同时借助 -} 语法,可将 Jinja2 标签与下一行内容合并。此时可使用回车键(Enter)或 Shift+Enter 对文本进行拆分排版,再通过上述的标签语法将拆分后的内容合并为一个整体,示例如下:
我的房子位于 {%- if living_in_town -%} 城市区域 {%- else -%} 乡村地区 {%- endif -%} ,我非常喜欢它。
渲染代码如下:
from docxtpl import DocxTemplate
tpl = DocxTemplate("template.docx")
context = {"living_in_town": True}
tpl.render(context)
tpl.save("output/output.docx")
表格
可以使用 colspan 标签实现表格单元格的水平合并:
{% colspan <var> %}
<var> 必须为整数,用于指定需要合并的列数。也可通过 Jinja2 模板引擎自动计算,如内置过滤器 count 通过管道符 | 接收 col_labels,用于统计其元素数量:
{% colspan col_labels|count %}
以下示例展示了如何利用 colspan 标签、tr 和 tc 标签动态填充一个表格:
from docxtpl import DocxTemplate
import os
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/dynamic_table_tpl.docx
tpl = DocxTemplate("templates/dynamic_table_tpl.docx")
context = {
"col_labels": ["fruit", "vegetable", "stone", "thing"],
"tbl_contents": [
{"label": "yellow", "cols": ["banana", "capsicum", "pyrite", "taxi"]},
{"label": "red", "cols": ["apple", "tomato", "cinnabar", "doubledecker"]},
{"label": "green", "cols": ["guava", "cucumber", "aventurine", "card"]},
],
}
tpl.render(context)
os.makedirs("output", exist_ok=True)
tpl.save("output/dynamic_table.docx")
也可以在 for 循环中实现单元格水平合并:
{% hm %}
以下代码展示了如何利用 hm 标签实现单元格水平合并:
from docxtpl import DocxTemplate
import os
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/horizontal_merge_tpl.docx
tpl = DocxTemplate("templates/horizontal_merge_tpl.docx")
tpl.render({})
os.makedirs("output", exist_ok=True)
tpl.save("output/horizontal_merge.docx")
此外,还可以在 for 循环中实现单元格垂直合并:
{% vm %}
以下示例展示了如何实现表格单元格的垂直合并效果:
from docxtpl import DocxTemplate
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/vertical_merge_tpl.docx
tpl = DocxTemplate("templates/vertical_merge_tpl.docx")
context = {
"items": [
{"desc": "Python interpreters", "qty": 2, "price": "FREE"},
{"desc": "Django projects", "qty": 5403, "price": "FREE"},
{"desc": "Guido", "qty": 1, "price": "100,000,000.00"},
],
"total_price": "100,000,000.00",
"category": "Book",
}
tpl.render(context)
tpl.save("output/vertical_merge.docx")
若需要修改表格单元格的背景色,必须将以下标签放置在单元格内容的最开头位置:
{% cellbg <var> %}
<var> 必须填写颜色的十六进制编码,且无需包含井号(#)。
1.2 复杂元素

1.2.1 富文本
富文本(Rich Text)是相对于纯文本(Plain Text)而言的一种文本格式。它不仅包含文字内容,还支持为文字添加各种格式属性及多媒体元素,从而呈现出更为丰富的视觉效果。这种格式的编辑和处理也可以通过在 Microsoft Word 软件中预先定义字符样式来实现。
在 python-docx-template 中使用富文本的步骤如下:
- 在 Word 模板中,为富文本定义一个占位符。例如,使用
{{r rich_text_var}},其中的 r 表示富文本。 - 在 Python 代码中,利用 RichText 类构建带有格式的文本内容。
- 渲染模板时,占位符会被替换为富文本内容,并保留所有已定义的格式样式。
在代码中使用 RichText 类时,还可通过以下标记控制文本格式:
- 换行:
; - 换段:
; - 分页:
。
以下为生成富文本 Word 文档的示例:
from docxtpl import DocxTemplate, RichText
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/richtext_tpl.docx
tpl = DocxTemplate("templates/richtext_tpl.docx")
rt = RichText()
# 向富文本对象中添加内容,依次演示不同的文本格式设置
rt.add("a rich text", style="myrichtextstyle")
# 使用自定义样式
rt.add(" with ")
rt.add("some italic", italic=True)
# 斜体文本
rt.add(" and ")
rt.add("some violet", color="#ff00ff")
# 紫色文本(十六进制颜色码)
rt.add(" and ")
rt.add("some striked", strike=True)
# 删除线文本
rt.add(" and ")
rt.add("some Highlighted", highlight="#ffff00")
# 黄色高亮文本
rt.add(" and ")
rt.add("some small", size=14)
# 小字号文本(14 磅)
rt.add(" or ")
rt.add("big", size=60)
# 大字号文本(60 磅)
rt.add(" text.")
rt.add("\nYou can add an hyperlink, here to ")
# 添加带超链接的文本,build_url_id 用于创建 URL 标识并关联到指定链接
rt.add("bing", url_id=tpl.build_url_id("http://bing.com"))
rt.add("\nEt voilà ! ")
# 演示换行符效果
rt.add("\n1st line")
rt.add("\n2nd line")
rt.add("\n3rd line")
# \n 用于创建新段落
rt.add("\nA new paragraph : <cool>\n")
# \f 用于插入分页符
rt.add("--- A page break here (see next page) ---\f")
# 循环演示不同类型的下划线样式
for ul in ["single", # 单下划线
"double", # 双下划线
"thick", # 粗下划线
"dotted", # 点下划线
"dash", # 短划线下划线
"dotDash", # 点划线下划线
"dotDotDash", # 双点划线下划线
"wave", # 波浪线下划线]:
rt.add("\nUnderline : "+ ul + " \n", underline=ul)
# 演示不同字体的设置
rt.add("\nFonts:\n", underline=True)
rt.add("Arial\n", font="Arial")
rt.add("Courier New\n", font="Courier New")
rt.add("Times New Roman\n", font="Times New Roman")
# 演示上标和下标文本
rt.add("\n\nHere some")
rt.add("superscript", superscript=True)
# 上标文本
rt.add(" and some")
rt.add("subscript", subscript=True)
# 下标文本
# 创建一个新的富文本对象,并将之前创建的 rt 对象嵌入其中,实现富文本嵌套
rt_embedded = RichText("an example of ")
rt_embedded.add(rt)
# 构建渲染上下文,将嵌套的富文本对象赋值给模板中的 "example" 变量
context = {"example": rt_embedded,}
# 将上下文数据渲染到 Word 模板中
tpl.render(context)
# 保存渲染后的 Word 文档到指定路径
tpl.save("output/richtext.docx")
1.2.2 富文本段落
若要精细控制单个段落的样式,可在代码中使用 RichTextParagraph() 或 RP() 对象。此对象需通过 {{p <var> }} 语法添加至模板。示例代码如下:
from docxtpl import DocxTemplate, RichText, RichTextParagraph
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/richtext_paragraph_tpl.docx
tpl = DocxTemplate("templates/richtext_paragraph_tpl.docx")
# 创建富文本段落对象组合不同样式的段落
rtp = RichTextParagraph()
# 创建富文本对象,用于设置文本的字符样式
rt = RichText()
# 向富文本段落中添加文本,并指定自定义样式 myrichparastyle
rtp.add("The rich text paragraph function allows paragraph styles to be added to text", parastyle="myrichparastyle",)
# 添加文本并使用内置段落样式 IntenseQuote
rtp.add("Any built in paragraph style can be used", parastyle="IntenseQuote")
# 添加文本并使用自定义样式 createdStyle
rtp.add("or you can add your own, unlocking all style options", parastyle="createdStyle")
# 添加文本并使用默认普通段落样式 normal
rtp.add("To use, just create a style in your template word doc with the formatting you want "
"and call it in the code.", parastyle="normal",)
# 演示不同列表样式的使用
rtp.add("This allows for the use of")
rtp.add("custom bullet\apoints", parastyle="SquareBullet")
# 方形项目符号样式
rtp.add("Numbered Bullet Points", parastyle="BasicNumbered")
# 数字编号样式
rtp.add("and Alpha Bullet Points.", parastyle="alphaBracketNumbering")
# 字母编号样式
# 演示文本对齐方式的设置
rtp.add("You can", parastyle="normal")
# 默认左对齐
rtp.add("set the", parastyle="centerAlign")
# 应用自定义样式居中对齐
rtp.add("text alignment", parastyle="rightAlign")
# 应用自定义样式右对齐
# 演示行间距样式:紧凑行间距
rtp.add("as well as the spacing between lines of text. Like this for example, "
"this text has very tight spacing between the lines.\nIt also has no space between "
"paragraphs of the same style.", parastyle="TightLineSpacing",)
# 演示行间距样式:宽行间距
rtp.add("Unlike this one, which has extra large spacing between lines for when you want to "
"space things out a bit or just write a little less.", parastyle="WideLineSpacing",)
# 演示段落背景色样式:绿色背景
rtp.add("You can also set the background colour of a line.", parastyle="LineShadingGreen")
# 构建富文本字符串,演示字符级样式
rt.add("This works with ")
rt.add("Rich ", bold=True)
# 加粗
rt.add("Text ", italic=True)
# 斜体
rt.add("Strings", underline="single")
# 单下划线
rt.add(" too.")
# 将富文本对象添加到富文本段落中,并指定方形项目符号样式
rtp.add(rt, parastyle="SquareBullet")
# 构建渲染上下文,将富文本段落对象绑定到模板中的 example 变量
context = {"example": rtp,}
# 将上下文数据渲染到 Word 模板中
tpl.render(context)
# 保存渲染后的 Word 文档到指定路径
tpl.save("output/richtext_paragraph.docx")
1.2.3 浮动对象
图片插入
可在文档中动态插入单张或多张图片,当前已支持 JPEG 和 PNG 格式。只需在模板中使用 {{ <var> }} 格式的标签即可。图片嵌入代码如下:
myimage = InlineImage(tpl, image_descriptor='test_files/python_logo.png', width=Mm(20), height=Mm(10))
使用时应传入模板对象与图片文件路径,宽高为可选参数。宽度和高度需通过 Mm(毫米)、Inches(英寸)或 Pt(磅)等类进行单位定义。示例代码如下:
from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm
import jinja2
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/inline_image_tpl.docx
tpl = DocxTemplate("templates/inline_image_tpl.docx")
# 定义渲染模板所需的上下文数据
context = {
# 只设置宽或者高,则图片自适应变化
"myimage": InlineImage(tpl, "templates/python_logo.png", width=Mm(20)),
# 手动指定宽高度
"myimageratio": InlineImage(tpl, "templates/python_jpeg.jpg", width=Mm(30), height=Mm(60)),
# 定义图片 + 描述
"frameworks": [
{"image": InlineImage(tpl, "templates/django.png", height=Mm(10)),
"desc": "The web framework for perfectionists with deadlines",},
{"image": InlineImage(tpl, "templates/zope.png", height=Mm(10)),
"desc": "Zope is a leading Open Source Application Server "
"and Content Management Framework",},
{"image": InlineImage(tpl, "templates/pyramid.png", height=Mm(10)),
"desc": "Pyramid is a lightweight Python web framework aimed at taking "
"small web apps into big web apps.",},
{"image": InlineImage(tpl, "templates/bottle.png", height=Mm(10)),
"desc": "Bottle is a fast, simple and lightweight WSGI micro web-framework "
"for Python",},
{"image": InlineImage(tpl, "templates/tornado.png", height=Mm(10)),
"desc": "Tornado is a Python web framework and asynchronous networking "
"library.",},
],
}
# autoescape 是否开启自动转义,把模板变量中的特殊字符转换成无害的 HTM 实体
jinja_env = jinja2.Environment(autoescape=True)
# 使用上下文数据和自定义的 jinja2 环境渲染 Word 模板
tpl.render(context, jinja_env)
tpl.save("output/inline_image.docx")
替换文档中的图片
可对文档中的现有图片进行替换,具体操作如下:先在模板中插入一张占位图,按常规流程渲染模板,之后再将占位图替换为目标图片。该方法支持批量处理文档内的所有媒体文件,且替换后的图片将维持原占位图的纵横比。在模板中插入图片时,只需指定文件名即可。该替换操作同时对页眉、页脚及正文区域生效。
例如,替换占位图 dummy_header_pic.jpg 的语法示例如下:
tpl.replace_pic('dummy_header_pic.jpg','header_pic_i_want.jpg')
注意,在将图片手动插入 Word 模板时,某些版本的 Word 会自动对其重命名并存储。这导致图片在 docx 文件内的实际文件名与原文件名完全不同,从而可能引发找不到图片的问题。若不确定图片的具体位置,可将 docx 文件视为 zip 压缩包进行解压,随后在 word\document.xml 文件中,通过查找 pic:nvPicPr 节点来定位图片信息。
在找到目标图片对应的 pic:nvPicPr 节点后,其 name 属性的值即为图片在文档中实际存储的文件名。此处的文件名可能不包含图片格式后缀,替换图片的示例代码可能如下:
tpl.replace_pic('Picture 1','header_pic_i_want.jpg')
1.2.4 子文档
模板变量可包含复杂的子文档对象,且能通过 python-docx 的文档操作方法从零构建。具体步骤为:先从模板对象中获取子文档对象,再将其当作 python-docx 文档对象使用。该功能需要安装额外依赖:
pip install "docxtpl[subdoc]"
以下代码展示了如何创建子文档,并将该子文档嵌入到主模板中,最终生成并保存新的文档:
from docxtpl import DocxTemplate
from docx.shared import Inches
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/subdoc_tpl.docx
# 1. 加载 Word 模板文件(指定模板文件路径)
tpl = DocxTemplate("templates/subdoc_tpl.docx")
# 2. 创建一个新的子文档对象
sd = tpl.new_subdoc()
# 3. 向下文档中添加段落内容
p = sd.add_paragraph("This is a sub-document inserted into a bigger one")
p = sd.add_paragraph("It has been ")
# 为文本片段设置自定义样式
p.add_run("dynamically").style = "dynamic"
p.add_run(" generated with python by using ")
# 为文本片段设置斜体样式
p.add_run("python-docx").italic = True
p.add_run(" library")
# 4. 向下文档添加标题
sd.add_heading("Heading, level 1", level=1)
# 向下文档添加带样式的段落(IntenseQuote 样式为内置样式)
sd.add_paragraph("This is an Intense quote", style="IntenseQuote")
# 5. 向下文档插入图片
sd.add_paragraph("A picture :")
sd.add_picture("templates/python_logo.png", width=Inches(1.25))
# 6. 向下文档插入表格
sd.add_paragraph("A Table :")
# 创建表格(初始 1 行 3 列,作为表头)
table = sd.add_table(rows=1, cols=3)
# 获取表头单元格并设置内容
hdr_cells = table.rows[0].cells
hdr_cells[0].text = "Qty"
hdr_cells[1].text = "Id"
hdr_cells[2].text = "Desc"
# 定义表格数据
recordset = ((1,101,"Spam"),(2,42,"Eggs"),(3,631,"Spam,spam, eggs, and ham"))
# 循环添加数据行到表格
for item in recordset:
row_cells = table.add_row().cells
row_cells[0].text = str(item[0]) # 数量(转为字符串)
row_cells[1].text = str(item[1]) # ID(转为字符串)
row_cells[2].text = item[2] # 描述
context = {"mysubdoc": sd,}
tpl.render(context)
tpl.save("output/subdoc.docx")
此外自 python-docx-template V0.12.0 版本起,支持将已有的.docx 文件作为子文档进行合并,如下所示:
from docxtpl import DocxTemplate
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates
tpl = DocxTemplate("templates/merge_docx_master_tpl.docx")
sd = tpl.new_subdoc("templates/merge_docx_subdoc.docx")
context = {"mysubdoc": sd,}
tpl.render(context)
tpl.save("output/merge_docx.docx")
1.3 补充操作

1.3.1 转义操作
默认情况下,python-docx-template 不会对内容进行转义。这是因为在使用模板语法修改 Word 文档时,底层实际上是在处理 XML 结构,而像 <、> 和 & 这样的字符在 XML 中具有特殊含义,必须经过转义才能正确显示。以下提供几种实现转义的方法:
调用 render 方法时启用自动转义,默认值为 autoescape=False:
tpl.render(context, autoescape=True)
上下文使用 escape() 函数处理内容,模板直接引用:
context = {'var': escape('my text')}
模板中写法:{{ <var> }}
上下文保持原始字符串,模板中使用 |e 过滤器:
context = {'var':'my text'}
模板中写法:{{ <var>|e }}
上下文定义时使用 R() 包裹内容,模板中添加 r 标记:
context = {'var': R('my text')}
模板中写法:{{r <var> }}
在文档中插入代码清单时,如果需要同时转义文本并处理换行符( )、段落符( )和换页符(),可以在 Python 代码中使用 Listing 类。
例如:
context = {'mylisting': Listing('the listing\nwith\nsome\nlines \n and some paragraph \n and special chars : <>&')}
在模板中直接引用即可:
{{ mylisting }}
使用 Listing() 能够保持当前字符样式,除非遇到 分隔符,它会在该位置开始一个新的段落。
使用示例如下:
from docxtpl import DocxTemplate, R, Listing
# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/escape_tpl.docx
tpl = DocxTemplate("templates/escape_tpl.docx")
context = {
"myvar": R('"less than" must be escaped : <, this can be done with RichText() or R()'),
"myescvar": 'It can be escaped with a "|e" jinja filter in the template too : < ',
"nlnp": R("Here is a multiple\nlines\nstring\nand some\nother\nparagraphs", color="#ff00ff",),
"mylisting": Listing("the listing\nwith\nsome\nlines\nand special chars : <>& ..."),
"page_break": R("\f"),
"new_listing": """ This is a new listing Here is a \t tab\n Here is a page break : \f That's it """,
"some_html": ("HTTP/1.1 200 OK\n"
"Server: Apache-Coyote/1.1\n"
"Cache-Control: no-store\n"),
}
tpl.render(context)
tpl.save("output/escape.docx")
此外,若需在最终生成的 Word 文档中显示由 Jinja2 渲染后的特殊字符 %、{ 或 },可以使用以下方式进行转义:
- 显示
%%→ 使用{_% %_} - 显示
{{ }}→ 使用{_{ }_}
1.3.2 获取未定义变量
要获取模板渲染时所需的未定义变量,可以按照以下步骤操作:
from docxtpl import DocxTemplate
tpl = DocxTemplate('template.docx')
context = {'name':'张三','age':30}
# 注意:department 变量未定义
# 检测缺失变量
missing = tpl.get_undeclared_template_variables(context=context)
print(f"缺失的变量:{missing}")
# 获取所有变量(不传 context)
all_vars = tpl.get_undeclared_template_variables()
print(f"模板所有变量:{all_vars}")
模板文档的内容包含:
姓名:{{name}} 年龄:{{age}} 部门:{{department}}
若未传递 context 参数,该方法将返回模板中所有需要赋值的变量名的集合。此结果可用于向用户提示输入,或写入文件供后续手动处理。
1.3.3 Jinja 自定义过滤器
Python-docx-template 的 render 方法支持一个可选参数 jinja_env,作为其第二个参数。通过传递自定义的 Jinja 环境对象,可以实现自定义过滤器的添加,从而灵活扩展数据处理逻辑。以下为具体示例。
模板 word 内容如下:
=== 姓名展示对比 === 原始名字:{{ name }} 方法 A (Python 处理): {{ name_upper }} 方法 B (模板过滤器): {{ name|upper }}
对应的 Python 渲染代码:
from docxtpl import DocxTemplate
import jinja2
# 准备数据
data = {'name':'zhangsan'}
# Python 中处理
data['name_upper']= data['name'].upper()
# 定义过滤器
def my_upper(text):
return text.upper()
doc = DocxTemplate("template.docx")
# 创建环境并注册过滤器
env = jinja2.Environment()
env.filters['upper']= my_upper
doc.render(data, env)
doc.save("output/compare.docx")
print(f"原始数据:{data['name']}")
print(f"Python 处理结果:{data['name_upper']}")
print(f"模板过滤器结果:{data['name'].upper()}")
1.3.4 Microsoft Word 2016 特殊行为说明
MS Word 2016 会忽略文档中的制表符,这是该版本特有的情况。类似 LibreOffice 或 WordPad 等其他编辑工具则无此问题。同样,以 Jinja2 标签开头且带有前导空格的行,其空格也会被忽略。
为解决上述问题,可使用 RichText 进行处理:
tpl.render({'test_space_r': RichText(' '),'test_tabs_r': RichText(5*' '),})
在模板中,通过 {{r ... }} 语法调用:
{{r test_space_r}} 空格将被保留 {{r test_tabs_r}} 制表符将正常显示


