docxtpl 是一个非常强大的库,它允许你使用 Jinja2 模板引擎来动态生成 Word 文档,这对于生成报告、合同、证书等需要填充个性化内容的文档尤其有用。

处理中文的核心在于 编码 和 字体,下面我将从安装、基础用法、中文处理要点到高级技巧,一步步为你讲解。
安装
确保你已经安装了 docxtpl,如果还没有,请在终端或命令行中运行:
pip install docxtpl
基础用法(不涉及中文)
在深入中文处理之前,我们先快速回顾一下 docxtpl 的基本工作流程:
- 创建一个 Word 模板 (
.docx):在 Word 中创建一个文档,将需要动态替换的部分用{{ variable_name }}标记。 - 准备数据:创建一个 Python 字典,键名对应模板中的
variable_name。 - 渲染文档:使用
docxtpl库加载模板和数据,生成一个新的.docx文件。
示例模板 (template.docx)

假设你在 Word 中创建了一个名为 template.docx 的文件,内容如下:
尊敬的 {{ name }}:
您好!这是您的 {{ document_type }}。
主要内容如下:
{% for item in content_list %}
- {{ item }}
{% endfor %}
此致
敬礼!
{{ company }}
{{ date }}
中文处理的核心要点
这是最关键的部分,要让中文在生成的 Word 文档中正确显示,你需要处理好两件事:模板的编码和字体的嵌入。
使用正确的字体
Word 文档的显示效果依赖于字体,如果你的系统上没有某个字体,Word 会尝试用其他字体替代,可能导致格式错乱或显示为方框。
解决方案:在模板中设置一个“通用”的中文字体

-
打开你的
template.docx文件。 -
选中所有文本(
Ctrl + A)。 -
在 Word 的字体设置中,选择一个常见且包含完整中文字符集的字体,
- 宋体
- 黑体
- 微软雅黑
- 楷体
推荐使用
SimSun(宋体) 或Microsoft YaHei(微软雅黑),因为它们在绝大多数 Windows 系统上都有预装。
为什么这么做?
通过在模板中预先设置好字体,docxtpl 在渲染时会保留这个字体设置,这样,即使在没有安装该字体的机器上打开文档,至少也能看到你选择的字体,而不是一个完全陌生的字体。
处理编码(Python 代码层面)
docxtpl 内部处理的是 .docx 文件,这是一种二进制格式,而不是纯文本文件,所以你通常不需要在 Python 代码中手动指定文件编码(如 utf-8),你只需要确保你的 Python 源代码文件(.py)本身是 utf-8 编码即可,这是现代 Python 的默认设置。
完整中文示例
让我们结合上面的要点,完成一个完整的中文文档生成示例。
第1步:创建模板
在 Word 中创建 template_chinese.docx如下,并将全文字体设置为“宋体”:
尊敬的 {{ name }} 先生/女士:
感谢您参加我们的活动,您的个人信息如下:
姓名:{{ name }}
公司:{{ company }}
职位:{{ position }}
活动议程:
{% for agenda_item in agenda %}
{{ loop.index }}. {{ agenda_item.time }} - {{ agenda_item.title }}
{% endfor %}
期待您的到来!
{{ organizer }}
{{ date }}
第2步:编写 Python 脚本
创建一个 generate_report.py 文件:
import docxtpl
from datetime import datetime
# 1. 准备数据(一个字典)
# 注意:agenda 是一个列表,列表中的元素也是字典,以支持复杂的循环
context = {
'name': '张三',
'company': '未来科技有限公司',
'position': '高级软件工程师',
'agenda': [
{'time': '09:00 - 09:30', 'title': '签到及欢迎致辞'},
{'time': '09:30 - 10:30', 'title': '人工智能发展趋势'},
{'time': '10:45 - 11:45', 'title': 'Python 自动化办公实践'},
],
'organizer': 'Python 爱好者协会',
'date': datetime.now().strftime('%Y年%m月%d日')
}
# 2. 加载模板
# 确保模板文件 'template_chinese.docx' 和脚本在同一目录下
try:
doc = docxtpl.DocxTemplate("template_chinese.docx")
except FileNotFoundError:
print("错误:请确保 'template_chinese.docx' 文件存在于脚本同一目录下。")
exit()
# 3. 渲染文档
# doc.render() 会将 context 中的数据填充到模板中
doc.render(context)
# 4. 保存生成的文档
output_filename = "活动邀请函_张三.docx"
doc.save(output_filename)
print(f"文档 '{output_filename}' 生成成功!")
第3步:运行脚本
在终端中运行:
python generate_report.py
第4步:查看结果
你会得到一个名为 活动邀请函_张三.docx 的新文件,打开它,你会发现所有的中文都正确地显示了出来,并且格式也和你设置的一样。
高级技巧
技巧1:插入图片
docxtpl 可以很方便地插入图片,你需要在模板中使用特定的语法,并在数据中提供图片路径。
模板语法:
{% img src="path/to/your/image.jpg" width="10" height="5" %}
src: 图片路径。width和height: 图片的尺寸,单位是厘米,你也可以只设置一个,另一个会自动按比例缩放。
Python 代码示例:
context = {
# ... 其他数据
'user_photo': 'path/to/user_photo.png' # 提供图片路径
}
# 在模板中这样使用:
# {% img src="{{ user_photo }}" width=4 %}
# 在 render 之前,需要告诉 docxtpl 这是一个图片文件
# doc.render(context) 会自动处理
技巧2:处理表格
表格的渲染非常直观,只需在模板中创建一个表格,并用 Jinja2 循环 {% for ... %} 填充单元格即可。
模板示例:
| 产品名称 | 数量 | 价格 |
| :--- | :--- | :--- |
| {% for product in products %} | | |
| {{ product.name }} | {{ product.quantity }} | {{ product.price }} |
| {% endfor %} | | |
| **总计** | | **{{ total_price }}** |
Python 代码示例:
products = [
{'name': '笔记本电脑', 'quantity': 1, 'price': 5999},
{'name': '无线鼠标', 'quantity': 2, 'price': 150},
{'name': '键盘', 'quantity': 1, 'price': 300}
]
total_price = sum(p['price'] * p['quantity'] for p in products)
context = {
'products': products,
'total_price': total_price
}
技巧3:处理长文本(自动换行)
当从数据库或文件中读取长文本并填入单元格时,可能会遇到自动换行的问题。docxtpl 提供了一个过滤器 linebreaksbr 来处理这个问题。
模板语法:
{{ long_text | linebreaksbr }}
它会将文本中的 \n (换行符) 转换成 Word 中的换行符。
常见问题与解决方案 (FAQ)
Q1: 生成的文档中,中文显示为方框或乱码怎么办?
A1: 这几乎 100% 是因为 字体问题。
- 检查模板:确保在 Word 模板中,你填充了中文的文本区域已经设置了一个包含中文字体的字体(如宋体、微软雅黑)。
- 检查系统:生成文档的机器和打开文档的机器是否都安装了该字体,如果目标机器没有,请考虑在模板中使用更通用的字体。
Q2: 为什么我明明设置了字体,但打开文档时字体还是变了?
A2: 这可能是因为你只对部分文本设置了字体,而没有全选,请务必在模板中 全选所有文本 (Ctrl + A) 然后统一设置字体。
Q3: 如何动态控制段落的显示/隐藏?
A3: 使用 Jinja2 的 if 语句。
模板语法:
{% if show_paragraph %}
这段文字只有在 show_paragraph 为 True 时才会显示。
{% endif %}
Python 代码:
context = {
'show_paragraph': True # 或 False
}
使用 docxtpl 处理中文 Word 文档,记住以下黄金法则:
- 模板先行:先在 Word 中设计好模板。
- 字体为王:全选模板文本,设置一个通用的中文字体(如宋体/微软雅黑)。
- 数据为实:用 Python 字典准备要填充的数据。
- 渲染生成:调用
docxtpl.DocxTemplate().render()和.save()完成生成。
遵循以上步骤,你就可以轻松、高效地生成各种复杂的中文 Word 文档了。
