找回密码
 立即注册
首页 业界区 业界 [python] python-docx-template模板化Word文档生成指北 ...

[python] python-docx-template模板化Word文档生成指北

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

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 标签说明
      • 1.1.2 常见元素

    • 1.2 复杂元素

      • 1.2.1 富文本
      • 1.2.2 富文本段落
      • 1.2.3 浮动对象
      • 1.2.4 子文档

    • 1.3 补充操作

      • 1.3.1 转义操作
      • 1.3.2 获取未定义变量
      • 1.3.3 Jinja自定义过滤器
      • 1.3.4 Microsoft Word 2016特殊行为说明


  • 2 参考

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模板语法标签,引擎会识别并执行其中的逻辑。一个完整的模板标签基本结构如下:
  1. {% 指令关键字 参数/条件 %}  // 起始标签
  2. 内容                      // 被标签控制的文本
  3. {% 结束关键字 %}          // 结束标签
复制代码
通过此类标签,python-docx-template可自动将标准Jinja2标签,即去除前缀p、tr、tc、r后的内容,精确嵌入到文档XML源码的相应位置。
2.jpeg

假设模板内容如下:
  1. {%p if display_paragraph %}
  2. 一段或多段文本内容
  3. {%p endif %}
复制代码
无论display_paragraph变量取值如何,首尾两个包含{%p ... %}标签的段落,都不会出现在最终生成的docx文档中。
只有当display_paragraph的值为True时,以下内容才会被保留在生成的文档里:
  1. 一段或多段文本内容
复制代码
对于模板里的标签格式需遵循如下要求,否则无法生成正确结果:

  • 起始标签分隔符后必须加空格,结束标签分隔符前必须加空格:

    • 错误示例:
      1. {%if something%}
      2. {%pif display_paragraph%}
      复制代码
    • 正确示例:
      1. {% if something %}
      2. {%p if display_paragraph %}
      复制代码

  • 同一段落、行、列或文本段内,禁止连续使用标签分隔符:

    • 错误示例:
      1. {%p{%tr{%tc{%r
      复制代码

  • 标签与内容不可写在同一行,需换行排版:

    • 错误示例:
      1. {%p if display_paragraph %}Here is my paragraph {%p endif %}
      复制代码
    • 正确示例:
      1. {%p if display_paragraph %}
      2. Here is my paragraph
      3. {%p endif %}
      复制代码

1.1.2 常见元素

显示变量
Jinja2模板里,可以用双大括号来显示变量:
  1. {{ <变量名> }}
复制代码
如果变量是普通字符串,字符串里的特殊符号会自动转换成对应的格式:

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

3.jpeg

1.2.1 富文本

富文本(Rich Text)是相对于纯文本(Plain Text)而言的一种文本格式。它不仅包含文字内容,还支持为文字添加各种格式属性及多媒体元素,从而呈现出更为丰富的视觉效果。这种格式的编辑和处理也可以通过在Microsoft Word软件中预先定义字符样式来实现。
在python-docx-template中使用富文本的步骤如下:

  • 在Word模板中,为富文本定义一个占位符。例如,使用{{r rich_text_var}},其中的r表示富文本。
  • 在Python代码中,利用RichText类构建带有格式的文本内容。
  • 渲染模板时,占位符会被替换为富文本内容,并保留所有已定义的格式样式。
在代码中使用RichText类时,还可通过以下标记控制文本格式:

  • 换行:\n;
  • 换段:\a;
  • 分页:\f。
以下为生成富文本Word文档的示例:
  1. # https://github.com/elapouya/python-docx-template/blob/master/tests/richtext.py
  2. from docxtpl import DocxTemplate, RichText
  3. # data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/richtext_tpl.docx
  4. tpl = DocxTemplate("templates/richtext_tpl.docx")
  5. rt = RichText()
  6. # 向富文本对象中添加内容,依次演示不同的文本格式设置
  7. rt.add("a rich text", )  # 使用自定义样式
  8. rt.add(" with ")                                
  9. rt.add("some italic", italic=True)              # 斜体文本
  10. rt.add(" and ")
  11. rt.add("some violet", color="#ff00ff")          # 紫色文本(十六进制颜色码)
  12. rt.add(" and ")
  13. rt.add("some striked", strike=True)             # 删除线文本
  14. rt.add(" and ")
  15. rt.add("some Highlighted", highlight="#ffff00") # 黄色高亮文本
  16. rt.add(" and ")
  17. rt.add("some small", size=14)                   # 小字号文本(14磅)
  18. rt.add(" or ")
  19. rt.add("big", size=60)                          # 大字号文本(60磅)
  20. rt.add(" text.")
  21. rt.add("\nYou can add an hyperlink, here to ")
  22. # 添加带超链接的文本,build_url_id 用于创建URL标识并关联到指定链接
  23. rt.add("bing", url_id=tpl.build_url_id("http://bing.com"))
  24. rt.add("\nEt voilà ! ")
  25. # 演示换行符效果
  26. rt.add("\n1st line")
  27. rt.add("\n2nd line")
  28. rt.add("\n3rd line")
  29. # \a 用于创建新段落
  30. rt.add("\aA new paragraph : <cool>\a")
  31. # \f 用于插入分页符
  32. rt.add("--- A page break here (see next page) ---\f")
  33. # 循环演示不同类型的下划线样式
  34. for ul in [
  35.     "single",       # 单下划线
  36.     "double",       # 双下划线
  37.     "thick",        # 粗下划线
  38.     "dotted",       # 点下划线
  39.     "dash",         # 短划线下划线
  40.     "dotDash",      # 点划线下划线
  41.     "dotDotDash",   # 双点划线下划线
  42.     "wave",         # 波浪线下划线
  43. ]:
  44.     rt.add("\nUnderline : " + ul + " \n", underline=ul)
  45. # 演示不同字体的设置
  46. rt.add("\nFonts :\n", underline=True)
  47. rt.add("Arial\n", font="Arial")               
  48. rt.add("Courier New\n", font="Courier New")   
  49. rt.add("Times New Roman\n", font="Times New Roman")
  50. # 演示上标和下标文本
  51. rt.add("\n\nHere some")
  52. rt.add("superscript", superscript=True)        # 上标文本
  53. rt.add(" and some")
  54. rt.add("subscript", subscript=True)            # 下标文本
  55. # 创建一个新的富文本对象,并将之前创建的rt对象嵌入其中,实现富文本嵌套
  56. rt_embedded = RichText("an example of ")
  57. rt_embedded.add(rt)
  58. # 构建渲染上下文,将嵌套的富文本对象赋值给模板中的 "example" 变量
  59. context = {
  60.     "example": rt_embedded,
  61. }
  62. # 将上下文数据渲染到Word模板中
  63. tpl.render(context)
  64. # 保存渲染后的Word文档到指定路径
  65. tpl.save("output/richtext.docx")
复制代码
1.2.2 富文本段落

若要精细控制单个段落的样式,可在代码中使用RichTextParagraph()或RP()对象。此对象需通过{{p  }}语法添加至模板。示例代码如下:
  1. # https://github.com/elapouya/python-docx-template/blob/master/tests/richtextparagraph.py
  2. from docxtpl import DocxTemplate, RichText, RichTextParagraph
  3. # data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/richtext_paragraph_tpl.docx
  4. tpl = DocxTemplate("templates/richtext_paragraph_tpl.docx")
  5. # 创建富文本段落对象组合不同样式的段落
  6. rtp = RichTextParagraph()
  7. # 创建富文本对象,用于设置文本的字符样式
  8. rt = RichText()
  9. # 向富文本段落中添加文本,并指定自定义样式myrichparastyle
  10. rtp.add(
  11.     "The rich text paragraph function allows paragraph styles to be added to text",
  12.     para,
  13. )
  14. # 添加文本并使用内置段落样式IntenseQuote
  15. rtp.add("Any built in paragraph style can be used", para)
  16. # 添加文本并使用自定义样式createdStyle
  17. rtp.add(
  18.     "or you can add your own, unlocking all style options", para
  19. )
  20. # 添加文本并使用默认普通段落样式normal
  21. rtp.add(
  22.     "To use, just create a style in your template word doc with the formatting you want "
  23.     "and call it in the code.",
  24.     para,
  25. )
  26. # 演示不同列表样式的使用
  27. rtp.add("This allows for the use of")
  28. rtp.add("custom bullet\apoints", para)  # 方形项目符号样式
  29. rtp.add("Numbered Bullet Points", para)  # 数字编号样式
  30. rtp.add("and Alpha Bullet Points.", para)  # 字母编号样式
  31. # 演示文本对齐方式的设置
  32. rtp.add("You can", para)  # 默认左对齐
  33. rtp.add("set the", para)  # 应用自定义样式居中对齐
  34. rtp.add("text alignment", para)  # 应用自定义样式右对齐
  35. # 演示行间距样式:紧凑行间距
  36. rtp.add(
  37.     "as well as the spacing between lines of text. Like this for example, "
  38.     "this text has very tight spacing between the lines.\aIt also has no space between "
  39.     "paragraphs of the same style.",
  40.     para,
  41. )
  42. # 演示行间距样式:宽行间距
  43. rtp.add(
  44.     "Unlike this one, which has extra large spacing between lines for when you want to "
  45.     "space things out a bit or just write a little less.",
  46.     para,
  47. )
  48. # 演示段落背景色样式:绿色背景
  49. rtp.add(
  50.     "You can also set the background colour of a line.", para
  51. )
  52. # 构建富文本字符串,演示字符级样式
  53. rt.add("This works with ")
  54. rt.add("Rich ", bold=True)  # 加粗
  55. rt.add("Text ", italic=True)  # 斜体
  56. rt.add("Strings", underline="single")  # 单下划线
  57. rt.add(" too.")
  58. # 将富文本对象添加到富文本段落中,并指定方形项目符号样式
  59. rtp.add(rt, para)
  60. # 构建渲染上下文,将富文本段落对象绑定到模板中的example变量
  61. context = {
  62.     "example": rtp,
  63. }
  64. # 将上下文数据渲染到 Word 模板中
  65. tpl.render(context)
  66. # 保存渲染后的 Word 文档到指定路径
  67. tpl.save("output/richtext_paragraph.docx")
复制代码
1.2.3 浮动对象

图片插入
可在文档中动态插入单张或多张图片,当前已支持JPEG和PNG格式。只需在模板中使用{{ <变量名> }}格式的标签即可。图片嵌入代码如下:
  1. myimage = InlineImage(tpl, image_descriptor='test_files/python_logo.png', width=Mm(20), height=Mm(10))
复制代码
使用时应传入模板对象与图片文件路径,宽高为可选参数。宽度和高度需通过Mm(毫米)、Inches(英寸)或 Pt(磅)等类进行单位定义。示例代码如下:
  1. # https://github.com/elapouya/python-docx-template/blob/master/tests/inline_image.py
  2. from docxtpl import DocxTemplate, InlineImage
  3. from docx.shared import Mm
  4. import jinja2
  5. # data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/inline_image_tpl.docx
  6. tpl = DocxTemplate("templates/inline_image_tpl.docx")
  7. # 定义渲染模板所需的上下文数据
  8. context = {
  9.     # 只设置宽或者高,则图片自适应变化
  10.     "myimage": InlineImage(tpl, "templates/python_logo.png", width=Mm(20)),
  11.     # 手动指定宽高度
  12.     "myimageratio": InlineImage(
  13.         tpl, "templates/python_jpeg.jpg", width=Mm(30), height=Mm(60)
  14.     ),
  15.     # 定义图片+描述
  16.     "frameworks": [
  17.         {
  18.             "image": InlineImage(tpl, "templates/django.png", height=Mm(10)),
  19.             "desc": "The web framework for perfectionists with deadlines",
  20.         },
  21.         {
  22.             "image": InlineImage(tpl, "templates/zope.png", height=Mm(10)),
  23.             "desc": "Zope is a leading Open Source Application Server "
  24.             "and Content Management Framework",
  25.         },
  26.         {
  27.             "image": InlineImage(tpl, "templates/pyramid.png", height=Mm(10)),
  28.             "desc": "Pyramid is a lightweight Python web framework aimed at taking "
  29.             "small web apps into big web apps.",
  30.         },
  31.         {
  32.             "image": InlineImage(tpl, "templates/bottle.png", height=Mm(10)),
  33.             "desc": "Bottle is a fast, simple and lightweight WSGI micro web-framework "
  34.             "for Python",
  35.         },
  36.         {
  37.             "image": InlineImage(tpl, "templates/tornado.png", height=Mm(10)),
  38.             "desc": "Tornado is a Python web framework and asynchronous networking "
  39.             "library.",
  40.         },
  41.     ],
  42. }
  43. # autoescape是否开启自动转义,把模板变量中的特殊字符转换成无害的HTM实体
  44. jinja_env = jinja2.Environment(autoescape=True)
  45. # 使用上下文数据和自定义的jinja2环境渲染Word模板
  46. tpl.render(context, jinja_env)
  47. tpl.save("output/inline_image.docx")
复制代码
替换文档中的图片
可对文档中的现有图片进行替换,具体操作如下:先在模板中插入一张占位图,按常规流程渲染模板,之后再将占位图替换为目标图片。该方法支持批量处理文档内的所有媒体文件,且替换后的图片将维持原占位图的纵横比。在模板中插入图片时,只需指定文件名即可。该替换操作同时对页眉、页脚及正文区域生效。
例如,替换占位图dummy_header_pic.jpg的语法示例如下:
  1. tpl.replace_pic('dummy_header_pic.jpg', 'header_pic_i_want.jpg')
复制代码
注意,在将图片手动插入Word模板时,某些版本的Word会自动对其重命名并存储。这导致图片在docx文件内的实际文件名与原文件名完全不同,从而可能引发找不到图片的问题。若不确定图片的具体位置,可将docx文件视为zip压缩包进行解压,随后在word\document.xml文件中,通过查找pic:nvPicPr节点来定位图片信息。具体步骤可参考:python使用docxtpl库对图片进行替换。
在找到目标图片对应的pic:nvPicPr节点后,其name属性的值即为图片在文档中实际存储的文件名。此处的文件名可能不包含图片格式后缀,替换图片的示例代码可能如下:
  1. tpl.replace_pic('Picture 1','header_pic_i_want.jpg')
复制代码
1.2.4 子文档

模板变量可包含复杂的子文档对象,且能通过python-docx的文档操作方法从零构建。具体步骤为:先从模板对象中获取子文档对象,再将其当作python-docx文档对象使用。该功能需要安装额外依赖:
pip install "docxtpl[subdoc]"
以下代码展示了如何创建子文档,并将该子文档嵌入到主模板中,最终生成并保存新的文档:
  1. # https://github.com/elapouya/python-docx-template/blob/master/tests/subdoc.py
  2. from docxtpl import DocxTemplate
  3. from docx.shared import Inches
  4. # data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/subdoc_tpl.docx
  5. # 1. 加载Word模板文件(指定模板文件路径)
  6. tpl = DocxTemplate("templates/subdoc_tpl.docx")
  7. # 2. 创建一个新的子文档对象
  8. sd = tpl.new_subdoc()
  9. # 3. 向下文档中添加段落内容
  10. p = sd.add_paragraph("This is a sub-document inserted into a bigger one")
  11. p = sd.add_paragraph("It has been ")
  12. # 为文本片段设置自定义样式
  13. p.add_run("dynamically").style = "dynamic"
  14. p.add_run(" generated with python by using ")
  15. # 为文本片段设置斜体样式
  16. p.add_run("python-docx").italic = True
  17. p.add_run(" library")
  18. # 4. 向下文档添加标题
  19. sd.add_heading("Heading, level 1", level=1)
  20. # 向下文档添加带样式的段落(IntenseQuote样式为内置样式)
  21. sd.add_paragraph("This is an Intense quote", )
  22. # 5. 向下文档插入图片
  23. sd.add_paragraph("A picture :")
  24. sd.add_picture("templates/python_logo.png", width=Inches(1.25))
  25. # 6. 向下文档插入表格
  26. sd.add_paragraph("A Table :")
  27. # 创建表格(初始1行3列,作为表头)
  28. table = sd.add_table(rows=1, cols=3)
  29. # 获取表头单元格并设置内容
  30. hdr_cells = table.rows[0].cells
  31. hdr_cells[0].text = "Qty"
  32. hdr_cells[1].text = "Id"
  33. hdr_cells[2].text = "Desc"
  34. # 定义表格数据
  35. recordset = ((1, 101, "Spam"), (2, 42, "Eggs"), (3, 631, "Spam,spam, eggs, and ham"))
  36. # 循环添加数据行到表格
  37. for item in recordset:
  38.     row_cells = table.add_row().cells
  39.     row_cells[0].text = str(item[0])  # 数量(转为字符串)
  40.     row_cells[1].text = str(item[1])  # ID(转为字符串)
  41.     row_cells[2].text = item[2]       # 描述
  42. context = {
  43.     "mysubdoc": sd,
  44. }
  45. tpl.render(context)
  46. tpl.save("output/subdoc.docx")
复制代码
此外自python-docx-template V0.12.0版本起,支持将已有的.docx文件作为子文档进行合并,如下所示:
  1. # https://github.com/elapouya/python-docx-template/blob/master/tests/merge_docx.py
  2. from docxtpl import DocxTemplate
  3. # data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates
  4. tpl = DocxTemplate("templates/merge_docx_master_tpl.docx")
  5. sd = tpl.new_subdoc("templates/merge_docx_subdoc.docx")
  6. context = {
  7.     "mysubdoc": sd,
  8. }
  9. tpl.render(context)
  10. tpl.save("output/merge_docx.docx")
复制代码
1.3 补充操作

4.jpeg

1.3.1 转义操作

默认情况下,python-docx-template不会对内容进行转义。这是因为在使用模板语法修改Word文档时,底层实际上是在处理XML结构,而像 和&这样的字符在XML中具有特殊含义,必须经过转义才能正确显示。以下提供几种实现转义的方法:

  • 上下文定义时使用R()包裹内容,模板中添加r标记:
    1. context = { 'var': R('my text') }
    复制代码
    模板中写法:{{r <变量名> }}
  • 上下文保持原始字符串,模板中使用|e过滤器:
    1. context = { 'var':'my text' }
    复制代码
    模板中写法:{{ |e }}
  • 上下文使用escape()函数处理内容,模板直接引用:
    1. context = { 'var': escape('my text') }
    复制代码
    模板中写法:{{ <变量名> }}
  • 调用render方法时启用自动转义,默认值为autoescape=False:
    1. tpl.render(context, autoescape=True)
    复制代码
在文档中插入代码清单时,如果需要同时转义文本并处理换行符(\n)、段落符(\a)和换页符(\f),可以在Python代码中使用Listing类。
例如:
  1. context = {
  2.     'mylisting': Listing('the listing\nwith\nsome\nlines \a and some paragraph \a and special chars : <>&')
  3. }
复制代码
在模板中直接引用即可:
  1. {{ mylisting }}
复制代码
使用Listing()能够保持当前字符样式,除非遇到\a分隔符,它会在该位置开始一个新的段落。
使用示例如下:
[code]# https://github.com/elapouya/python-docx-template/blob/master/tests/escape.pyfrom docxtpl import DocxTemplate, R, Listing# data: https://github.com/elapouya/python-docx-template/blob/master/tests/templates/escape_tpl.docxtpl = DocxTemplate("templates/escape_tpl.docx")context = {    "myvar": R(        '"less than" must be escaped :

相关推荐

2026-1-23 09:54:40

举报

您需要登录后才可以回帖 登录 | 立即注册