文章目录
- 分离内容与格式:模板负责排版样式,代码负责逻辑与数据。 复用性强:一份模板可用于成百上千次不同数据的生成。 所见即所得:模板在 Word 中编辑,格式所见即所得,无需写 XML 或 CSS。 支持复杂逻辑:借助 Jinja2,支持变量、循环、条件判断、过滤器等。
- 库名 功能 优点 缺点 python-docx 创建/修改 .docx 轻量、直接操作文档对象 需手写所有内容和格式,不适合复杂排版 docxtpl 基于模板生成 .docx 保留原格式、支持 Jinja2 逻辑、开发效率高 依赖模板,无法动态创建全新结构 pywin32 调用 Word COM 接口 功能最全(支持 .doc、宏等) 仅限 Windows,需安装 Word,不稳定 pandoc 格式转换(Markdown → .docx) 跨平台、支持多种输入 格式控制弱,难以精细排版 结论:如果你已有固定格式的 Word 文档(如合同、证书、报告),且需要批量填充不同数据,docxtpl 是最优解。
- 打开 Microsoft Word(或 LibreOffice Writer,保存为 .docx)。 输入内容,并插入 Jinja2 占位符。例如: 尊敬的 {{ customer_name }}: 您好!您于 {{ order_date }} 下单的订单(编号:{{ order_id }})已发货。 商品清单: {% for item in items %} – {{ item.name }} × {{ item.quantity }} {% endfor %} 感谢您的支持! 保存为 order_template.docx。
- from docxtpl import DocxTemplate # 加载模板 doc = DocxTemplate(“order_template.docx”) # 准备数据 context = { “customer_name”: “张三”, “order_date”: “2026-01-12”, “order_id”: “ORD20260112001”, “items”: [ {“name”: “无线耳机”, “quantity”: 2}, {“name”: “手机支架”, “quantity”: 1} ] } # 渲染并保存 doc.render(context) doc.save(“张三_订单通知.docx”) 运行后,将生成一份格式完整、内容填充好的 Word 文档!
- 最基础的功能。在模板中使用 {{ variable_name }},在 context 字典中提供对应值。 支持的数据类型: 字符串、数字、布尔值 datetime 对象(可配合格式化) 自定义对象(需有属性或 __str__ 方法) from datetime import datetime context = { “today”: datetime.now(), “is_vip”: True, “score”: 95.5 } 模板中: 日期:{{ today.strftime(‘%Y年%m月%d日’) }} VIP:{% if is_vip %}是{% else %}否{% endif %} 分数:{{ “%.1f”|format(score) }} 注意:Jinja2 的 strftime 需要对象本身支持,datetime 默认支持。
- 使用 {% for item in list %}…{% endfor %} 遍历列表或字典。
- 模板中的表格(Word 表格): 商品名 数量 单价 {{ item.name }} {{ item.qty }} ¥{{ item.price }} 但这样只能填一行。正确做法是: 在 Word 中只保留表头。 在表头下方插入一个“循环块”,包含一行带占位符的表格行。 模板写法(在 Word 中): {% for item in products %} {{ item.name }} {{ item.qty }} ¥{{ item.price }} {% endfor %} 技巧:在 Word 中按 Tab 可创建表格,或直接复制一行作为模板行。
- {% for p in products %} {{ p.name }} {{ p.qty }} {{ p.price }} {{ p.qty * p.price }} {% endfor %} 总计: {{ products|sum(attribute=’price’) }} 是 Jinja2 内置过滤器,但注意:products|sum(attribute='qty*price') 不支持表达式,需在 Python 中预计算。
- 使用 {% if condition %}…{% elif %}…{% else %}…{% endif %}。 {% if user.age >= 18 %} 您已成年,可参与抽奖。 {% else %} 未成年用户不可参与。 {% endif %} 支持逻辑运算:and、or、not,比较运算:==, !=, >, < 等。
- Jinja2 提供丰富过滤器,也可自定义。 常用内置过滤器: upper / lower:大小写转换 default('N/A'):默认值 length:获取长度 round(2):四舍五入 replace(' ', '_'):字符串替换 邮箱:{{ email|default(‘未提供’)|lower }}
- docxtpl 支持在模板中动态插入图片。 步骤: 在模板中使用 {{ image_variable }} 占位。 在 context 中传入 InlineImage 对象。 from docxtpl import DocxTemplate, InlineImage from docx.shared import Mm doc = DocxTemplate(“template.docx”) context = { “logo”: InlineImage(doc, ‘logo.png’, width=Mm(30)) } doc.render(context) doc.save(“output.docx”) 注意: 图片路径可以是本地文件、BytesIO 流。 必须指定宽度或高度(单位:Mm, Inches, Pt 等)。 不支持直接传字符串路径,必须包装为 InlineImage。
- Jinja2 支持 include,但 docxtpl 不支持跨文件 include,因为 Word 模板是二进制文件,无法像 HTML 那样拆分。 替代方案: 在主模板中预留区域,通过条件判断渲染不同内容。 使用多个模板文件,程序逻辑选择使用哪个。
- 模板内容: {{ company_name }} 录用通知书 尊敬的 {{ candidate_name }} 先生/女士: 经面试评估,我们诚挚邀请您加入 {{ department }} 部门,担任 {{ position }} 一职。 入职日期:{{ start_date }} 月薪:¥{{ salary }} 此致 敬礼! {{ company_name }} 人力资源部 {{ issue_date }} Python 脚本: candidates = [ {“name”: “李四”, “dept”: “技术部”, “pos”: “后端工程师”, “salary”: 18000}, {“name”: “王五”, “dept”: “市场部”, “pos”: “运营专员”, “salary”: 10000} ] for c in candidates: context = { “company_name”: “星辰科技”, “candidate_name”: c[“name”], “department”: c[“dept”], “position”: c[“pos”], “salary”: c[“salary”], “start_date”: “2026-02-01”, “issue_date”: “2026-01-12” } doc = DocxTemplate(“offer_template.docx”) doc.render(context) doc.save(f”录用通知_{c[‘name’]}.docx”)
- 模板表格结构(含循环): 课程 成绩 等级 {% for course in courses %}{{ course.name }} {{ course.score }} {{ course.grade }}{% endfor %} 数据: students = [ { “name”: “赵六”, “id”: “2023001”, “courses”: [ {“name”: “高等数学”, “score”: 88, “grade”: “B+”}, {“name”: “Python编程”, “score”: 95, “grade”: “A”} ], “average”: 91.5 } ] 技巧:可在循环外显示平均分、排名等汇总信息。
- A:docxtpl 基于 python-docx,而 .docx 本身支持 Unicode,不会乱码。若出现乱码,请检查: Python 文件是否为 UTF-8 编码 Word 模板是否使用了特殊字体(建议用宋体、微软雅黑等常见字体)
- A:确保循环行与表头在同一表格内;避免在循环中插入换行符;使用 Word 的“表格属性”统一列宽。
- A: 单个文档生成很快(毫秒级)。 批量生成时,建议使用多线程或异步(但注意 GIL)。 避免在循环中重复加载模板(应在外层加载一次,多次 render)。
- A:不支持。.doc 是旧版二进制格式,docxtpl 仅支持 .docx(Office Open XML)。可先用 Word 将 .doc 另存为 .docx。
- A:可以! 在 Word 模板中编辑页眉页脚,同样可使用 {{ variable }} 占位。
目录
- 引言
- 一、什么是 docxtpl?
- 1.1 设计理念
- 1.2 与其他库的对比
- 二、安装与环境准备
- 2.1 安装
- 2.2 环境要求
- 三、快速入门:5 分钟上手
- 3.1 创建模板文件
- 3.2 编写 Python 脚本
- 四、核心功能详解
- 4.1 变量替换(Variables)
- 4.2 循环(Loops)
- 示例:生成表格
- 复杂表格示例(含合计):
- 4.3 条件判断(Conditionals)
- 4.4 过滤器(Filters)
- 自定义过滤器
- 4.5 图片插入
- 4.6 子模板与 include(高级)
- 五、实战案例
- 案例 1:批量生成员工录用通知书
- 案例 2:学生成绩单生成
- 六、常见问题与解决方案
- Q1:中文乱码?
- Q2:表格格式错乱?
- Q3:如何处理大量数据(性能)?
- Q4:支持 .doc 格式吗?
- Q5:能生成页眉页脚吗?
- 七、最佳实践建议
- 八、总结
在现代办公自动化、数据报告生成、批量文档处理等场景中,如何高效、准确地生成格式统一且内容动态的 Word 文档,一直是开发者和业务人员关注的重点。虽然 Microsoft Word 本身功能强大,但手动操作不仅耗时,还容易出错。而 Python 作为一门通用编程语言,在自动化领域表现尤为突出。其中,docxtpl 库凭借其简洁的 API 和强大的模板能力,成为生成 .docx 文档的首选工具之一。
本文将全面、深入地介绍 docxtpl 库:从基本概念、安装配置,到核心功能详解、高级用法、实战案例,再到常见问题与性能优化建议,帮助读者真正掌握这一高效工具,并将其应用于实际项目中。
docxtpl(全称:Docx Template)是一个基于 Jinja2 模板引擎 和 python-docx 库构建的 Python 第三方库。它的核心思想是“模板 + 数据 = 文档”——你只需预先设计好一个 Word 模板文件(.docx 格式),在其中使用 Jinja2 风格的占位符(如 {{ name }}、{% for item in items %} 等),然后通过 Python 脚本传入数据字典,即可自动生成填充后的 Word 文档。
- 分离内容与格式:模板负责排版样式,代码负责逻辑与数据。
- 复用性强:一份模板可用于成百上千次不同数据的生成。
- 所见即所得:模板在 Word 中编辑,格式所见即所得,无需写 XML 或 CSS。
- 支持复杂逻辑:借助 Jinja2,支持变量、循环、条件判断、过滤器等。
| 库名 | 功能 | 优点 | 缺点 |
|---|---|---|---|
| python-docx | 创建/修改 .docx | 轻量、直接操作文档对象 | 需手写所有内容和格式,不适合复杂排版 |
| docxtpl | 基于模板生成 .docx | 保留原格式、支持 Jinja2 逻辑、开发效率高 | 依赖模板,无法动态创建全新结构 |
| pywin32 | 调用 Word COM 接口 | 功能最全(支持 .doc、宏等) | 仅限 Windows,需安装 Word,不稳定 |
| pandoc | 格式转换(Markdown → .docx) | 跨平台、支持多种输入 | 格式控制弱,难以精细排版 |
结论:如果你已有固定格式的 Word 文档(如合同、证书、报告),且需要批量填充不同数据,docxtpl 是最优解。
pip install docxtpl
该命令会自动安装依赖项 python-docx 和 Jinja2。
提示:建议在虚拟环境中安装,避免依赖冲突。
- Python 3.6+
- 操作系统:Windows / macOS / Linux(跨平台)
- 不需要安装 Microsoft Word(纯 Python 实现)
- 打开 Microsoft Word(或 LibreOffice Writer,保存为
.docx)。
- 输入内容,并插入 Jinja2 占位符。例如:
尊敬的 {{ customer_name }}:
您好!您于 {{ order_date }} 下单的订单(编号:{{ order_id }})已发货。
商品清单:
{% for item in items %}
- {{ item.name }} × {{ item.quantity }}
{% endfor %}
感谢您的支持!
- 保存为
order_template.docx。
.docx)。order_template.docx。
from docxtpl import DocxTemplate
# 加载模板
doc = DocxTemplate("order_template.docx")
# 准备数据
context = {
"customer_name": "张三",
"order_date": "2026-01-12",
"order_id": "ORD20260112001",
"items": [
{"name": "无线耳机", "quantity": 2},
{"name": "手机支架", "quantity": 1}
]
}
# 渲染并保存
doc.render(context)
doc.save("张三_订单通知.docx")
运行后,将生成一份格式完整、内容填充好的 Word 文档!
最基础的功能。在模板中使用 {{ variable_name }},在 context 字典中提供对应值。
支持的数据类型:
- 字符串、数字、布尔值
datetime对象(可配合格式化)- 自定义对象(需有属性或
__str__方法)
from datetime import datetime
context = {
"today": datetime.now(),
"is_vip": True,
"score": 95.5
}
模板中:
日期:{{ today.strftime('%Y年%m月%d日') }}
VIP:{% if is_vip %}是{% else %}否{% endif %}
分数:{{ "%.1f"|format(score) }}
注意:Jinja2 的 strftime 需要对象本身支持,datetime 默认支持。
使用 {% for item in list %}...{% endfor %} 遍历列表或字典。
模板中的表格(Word 表格):
| 商品名 | 数量 | 单价 |
|---|---|---|
| {{ item.name }} | {{ item.qty }} | ¥{{ item.price }} |
但这样只能填一行。正确做法是:
- 在 Word 中只保留表头。
- 在表头下方插入一个“循环块”,包含一行带占位符的表格行。
模板写法(在 Word 中):
{% for item in products %}
{{ item.name }} {{ item.qty }} ¥{{ item.price }}
{% endfor %}
技巧:在 Word 中按 Tab 可创建表格,或直接复制一行作为模板行。
{% for p in products %}
{{ p.name }} {{ p.qty }} {{ p.price }} {{ p.qty * p.price }}
{% endfor %}
总计: {{ products|sum(attribute='price') }}
是 Jinja2 内置过滤器,但注意:products|sum(attribute='qty*price') 不支持表达式,需在 Python 中预计算。
使用 {% if condition %}...{% elif %}...{% else %}...{% endif %}。
{% if user.age >= 18 %}
您已成年,可参与抽奖。
{% else %}
未成年用户不可参与。
{% endif %}
支持逻辑运算:and、or、not,比较运算:==, !=, >, < 等。
Jinja2 提供丰富过滤器,也可自定义。
常用内置过滤器:
upper/lower:大小写转换default('N/A'):默认值length:获取长度round(2):四舍五入replace(' ', '_'):字符串替换
邮箱:{{ email|default('未提供')|lower }}
def add_prefix(value, prefix="ID:"):
return f"{prefix}{value}"
doc = DocxTemplate("template.docx")
doc.render(context, autoescape=True, jinja_env={"autoescape": True})
# 注册过滤器
from jinja2 import Environment
env = Environment()
env.filters['add_prefix'] = add_prefix
doc.render(context, jinja_env=env)
✅ 更推荐方式:通过 DocxTemplate 的 render() 方法传入 jinja_env。
docxtpl 支持在模板中动态插入图片。
步骤:
- 在模板中使用
{{ image_variable }}占位。 - 在 context 中传入
InlineImage对象。
from docxtpl import DocxTemplate, InlineImage
from docx.shared import Mm
doc = DocxTemplate("template.docx")
context = {
"logo": InlineImage(doc, 'logo.png', width=Mm(30))
}
doc.render(context)
doc.save("output.docx")
注意:
- 图片路径可以是本地文件、BytesIO 流。
- 必须指定宽度或高度(单位:Mm, Inches, Pt 等)。
- 不支持直接传字符串路径,必须包装为 InlineImage。
Jinja2 支持 include,但 docxtpl 不支持跨文件 include,因为 Word 模板是二进制文件,无法像 HTML 那样拆分。
替代方案:
- 在主模板中预留区域,通过条件判断渲染不同内容。
- 使用多个模板文件,程序逻辑选择使用哪个。
模板内容:
{{ company_name }} 录用通知书
尊敬的 {{ candidate_name }} 先生/女士:
经面试评估,我们诚挚邀请您加入 {{ department }} 部门,担任 {{ position }} 一职。
入职日期:{{ start_date }}
月薪:¥{{ salary }}
此致
敬礼!
{{ company_name }} 人力资源部
{{ issue_date }}
Python 脚本:
candidates = [
{"name": "李四", "dept": "技术部", "pos": "后端工程师", "salary": 18000},
{"name": "王五", "dept": "市场部", "pos": "运营专员", "salary": 10000}
]
for c in candidates:
context = {
"company_name": "星辰科技",
"candidate_name": c["name"],
"department": c["dept"],
"position": c["pos"],
"salary": c["salary"],
"start_date": "2026-02-01",
"issue_date": "2026-01-12"
}
doc = DocxTemplate("offer_template.docx")
doc.render(context)
doc.save(f"录用通知_{c['name']}.docx")
模板表格结构(含循环):
| 课程 | 成绩 | 等级 |
|---|---|---|
| {% for course in courses %}{{ course.name }} {{ course.score }} {{ course.grade }}{% endfor %} |
数据:
students = [
{
"name": "赵六",
"id": "2023001",
"courses": [
{"name": "高等数学", "score": 88, "grade": "B+"},
{"name": "Python编程", "score": 95, "grade": "A"}
],
"average": 91.5
}
]
技巧:可在循环外显示平均分、排名等汇总信息。
A:docxtpl 基于 python-docx,而 .docx 本身支持 Unicode,不会乱码。若出现乱码,请检查:
- Python 文件是否为 UTF-8 编码
- Word 模板是否使用了特殊字体(建议用宋体、微软雅黑等常见字体)
A:确保循环行与表头在同一表格内;避免在循环中插入换行符;使用 Word 的“表格属性”统一列宽。
A:
- 单个文档生成很快(毫秒级)。
- 批量生成时,建议使用多线程或异步(但注意 GIL)。
- 避免在循环中重复加载模板(应在外层加载一次,多次 render)。
A:不支持。.doc 是旧版二进制格式,docxtpl 仅支持 .docx(Office Open XML)。可先用 Word 将 .doc 另存为 .docx。
A:可以! 在 Word 模板中编辑页眉页脚,同样可使用 {{ variable }} 占位。
- 模板命名规范:如
contract_template.docx,清晰表明用途。
- 数据预处理:在 Python 中完成计算、格式化,模板只负责展示。
- 错误处理:捕获
Jinja2TemplateError 等异常。
- 版本控制:将模板文件纳入 Git 管理,便于协作与回滚。
- 测试覆盖:对关键模板编写单元测试,验证输出内容。
contract_template.docx,清晰表明用途。Jinja2TemplateError 等异常。
docxtpl 是连接 Python 数据处理能力与 Word 排版优势的桥梁。它让非程序员也能通过熟悉的 Word 设计模板,而开发者则能用简洁代码实现自动化文档生成。无论是 HR 发送 offer、财务生成报表,还是教育机构打印成绩单,docxtpl 都能大幅提升效率,减少人为错误。
掌握它,你就拥有了一个强大的办公自动化武器。现在,就去试试吧!
以上就是Python使用docxtpl库高效生成Word文档的方法的详细内容,更多关于Python docxtpl生成Word文档的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Python3使用win32com从Excel读取数据生成Word格式报告批量发邮件的示例详解
- Python实现Word文档自动化的操作大全(批量生成、模板填充与内容修改)
- Python轻松实现Word文档对比并生成可视化HTML报告
- Python从Word文档中提取图片并生成PPT的操作代码
- Python利用python-docx实现自动生成Word文档