最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python使用python-docx-template實現(xiàn)模板化Word文檔生成指南

 更新時間:2026年01月21日 09:00:49   作者:落痕的寒假  
python-docx庫的核心功能是程序化創(chuàng)建全新的Word文檔,但在基于已有模板替換其部分內容時,其操作會非常繁瑣,python-docx-template正是為解決這一痛點而設計的,下面我們就來看看該如何使用它吧

python-docx庫的核心功能是程序化創(chuàng)建全新的Word文檔,但在基于已有模板替換其部分內容時,其操作會非常繁瑣。用戶需要先解析文檔結構、定位具體位置、手動替換內容,并維護原有格式與布局,導致開發(fā)效率較低。相關使用方法可參考:python基于python-docx庫自動化處理Word文檔的完整指南 

python-docx-template正是為解決這一痛點而設計的。它借鑒Jinja2模板引擎的思路,允許在Word文檔中直接插入類似{{variable}}的占位符,隨后僅用幾行代碼即可完成數(shù)據(jù)填充,無需關心底層文檔結構,完美適配基于模板修改文檔的場景。

python-docx-template基于python-docx實現(xiàn)文檔讀寫功能,并借助jinja2提供靈活的模板標簽支持,其設計思路如下:

  • 用Word制作模板:在Microsoft Word中自由設計文檔格式,如插入圖片、設置頁眉頁腳、調整表格樣式,充分利用Word強大的排版功能。
  • 插入模板變量:在需要動態(tài)內容的位置,直接輸入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庫的正式分發(fā)名稱,二者指代同一工具。

核心概念

標簽說明

python-docx-template允許在Word文檔中使用Jinja2標簽和過濾器。但為確保其在Word中正常運作,需遵循若干限制。

常規(guī)Jinja2標簽僅能在同一段落內且同一文本運行中使用,若需控制段落、表格行或包含樣式的完整文本運行,則必須使用后續(xù)章節(jié)介紹的復雜元素標簽語法。

舉例而言,若創(chuàng)建一個所有字符樣式相同的段落,Word內部只會生成一個文本運行對象。但若在該段落中將部分文字設置為加粗,Word會將原有文本運行拆分為三個獨立部分,分別對應普通樣式、加粗樣式及恢復后的普通樣式。

標簽

若要對段落、表格行、表格列以及文本段進行管理,需使用以下專用語法:

  • 段落標簽:{%p jinja2_tag %}
  • 表格行標簽:{%tr jinja2_tag %}
  • 表格列標簽:{%tc jinja2_tag %}
  • 文本段標簽:{%r jinja2_tag %}

這些以{% %}包裹的內容是Jinja2模板語法標簽,引擎會識別并執(zhí)行其中的邏輯。一個完整的模板標簽基本結構如下:

{% 指令關鍵字 參數(shù)/條件 %}  // 起始標簽
內容                      // 被標簽控制的文本
{% 結束關鍵字 %}          // 結束標簽

通過此類標簽,python-docx-template可自動將標準Jinja2標簽,即去除前綴p、trtcr后的內容,精確嵌入到文檔XML源碼的相應位置。

假設模板內容如下:

{%p if display_paragraph %}
一段或多段文本內容
{%p endif %}

無論display_paragraph變量取值如何,首尾兩個包含{%p ... %}標簽的段落,都不會出現(xiàn)在最終生成的docx文檔中。

只有當display_paragraph的值為True時,以下內容才會被保留在生成的文檔里:

一段或多段文本內容

對于模板里的標簽格式需遵循如下要求,否則無法生成正確結果:

起始標簽分隔符后必須加空格,結束標簽分隔符前必須加空格:

錯誤示例:

{%if something%}
{%pif display_paragraph%}

正確示例:

{% if something %}
{%p if display_paragraph %}

同一段落、行、列或文本段內,禁止連續(xù)使用標簽分隔符:

錯誤示例:

{%p{%tr{%tc{%r

標簽與內容不可寫在同一行,需換行排版:

錯誤示例:

{%p if display_paragraph %}Here is my paragraph {%p endif %}

正確示例:

{%p if display_paragraph %}
Here is my paragraph
{%p endif %}

常見元素

顯示變量

Jinja2模板里,可以用雙大括號來顯示變量:

{{ <變量名> }}

如果變量是普通字符串,字符串里的特殊符號會自動轉換成對應的格式:

  • \n → 換行
  • \a → 分段
  • \t → 制表符(按一下 Tab 鍵的效果)
  • \f → 分頁符

如果變量是富文本(RichText)對象,必須在變量名前加一個r,明確表示要渲染這個富文本內容:

{{r <變量名> }}

注意,r要緊跟在左大括號的后面。

此外,變量名中禁止直接使用<,>, &這類字符,除非用了轉義語法。

注釋

可以在模板中添加類Jinja2風格的注釋,注釋不會被渲染到最終文件:

{#p 這是一個段落類型的注釋 #}
{#tr 這是一個表格行類型的注釋 #}
{#tc 這是一個表格單元格類型的注釋 #}

在執(zhí)行如下代碼對模板文件進行渲染操作時,模板中原有的所有注釋信息均會被清除,不會保留在最終的渲染結果中:

# https://github.com/elapouya/python-docx-template/blob/master/tests/comments.py
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 %}城市區(qū)域{% else %}鄉(xiāng)村地區(qū){% endif %},我非常喜歡它。

借助{%-語法,可將Jinja2標簽與上一行內容合并,同時借助-%}語法,可將Jinja2標簽與下一行內容合并。此時可使用回車鍵(Enter)或Shift+Enter對文本進行拆分排版,再通過上述的標簽語法將拆分后的內容合并為一個整體,示例如下:

我的房子位于
{%- if living_in_town -%}
城市區(qū)域
{%- else -%}
鄉(xiāng)村地區(qū)
{%- endif -%}
,我非常喜歡它。

渲染代碼如下:

from docxtpl import DocxTemplate
tpl = DocxTemplate("template.docx")
context = {"living_in_town": True}

tpl.render(context)
tpl.save("output/output.docx")

表格

可以使用colspan標簽實現(xiàn)表格單元格的水平合并:

{% colspan <var> %}

<var>必須為整數(shù),用于指定需要合并的列數(shù)。也可通過Jinja2模板引擎自動計算,如內置過濾器count通過管道符|接收col_labels,用于統(tǒng)計其元素數(shù)量:

{% colspan col_labels|count %}

以下示例展示了如何利用colspan標簽、trtc標簽動態(tài)填充一個表格:

# https://github.com/elapouya/python-docx-template/blob/master/tests/dynamic_table.py
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循環(huán)中實現(xiàn)單元格水平合并:

{% hm %}

以下代碼展示了如何利用hm標簽實現(xiàn)單元格水平合并:

# https://github.com/elapouya/python-docx-template/blob/master/tests/horizontal_merge.py
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循環(huán)中實現(xiàn)單元格垂直合并:

{% vm %}

以下示例展示了如何實現(xiàn)表格單元格的垂直合并效果:

# https://github.com/elapouya/python-docx-template/blob/master/tests/vertical_merge.py
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>必須填寫顏色的十六進制編碼,且無需包含井號(#)。

復雜元素

富文本

富文本(Rich Text)是相對于純文本(Plain Text)而言的一種文本格式。它不僅包含文字內容,還支持為文字添加各種格式屬性及多媒體元素,從而呈現(xiàn)出更為豐富的視覺效果。這種格式的編輯和處理也可以通過在Microsoft Word軟件中預先定義字符樣式來實現(xiàn)。

在python-docx-template中使用富文本的步驟如下:

  • 在Word模板中,為富文本定義一個占位符。例如,使用{{r rich_text_var}},其中的r表示富文本。
  • 在Python代碼中,利用RichText類構建帶有格式的文本內容。
  • 渲染模板時,占位符會被替換為富文本內容,并保留所有已定義的格式樣式。

在代碼中使用RichText類時,還可通過以下標記控制文本格式:

  • 換行:\n;
  • 換段:\a;
  • 分頁:\f。

以下為生成富文本W(wǎng)ord文檔的示例:

# https://github.com/elapouya/python-docx-template/blob/master/tests/richtext.py
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 用于創(chuàng)建URL標識并關聯(lián)到指定鏈接
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")
# \a 用于創(chuàng)建新段落
rt.add("\aA new paragraph : <cool>\a")
# \f 用于插入分頁符
rt.add("--- A page break here (see next page) ---\f")

# 循環(huán)演示不同類型的下劃線樣式
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)            # 下標文本

# 創(chuàng)建一個新的富文本對象,并將之前創(chuàng)建的rt對象嵌入其中,實現(xiàn)富文本嵌套
rt_embedded = RichText("an example of ")
rt_embedded.add(rt)

# 構建渲染上下文,將嵌套的富文本對象賦值給模板中的 "example" 變量
context = {
    "example": rt_embedded,
}

# 將上下文數(shù)據(jù)渲染到Word模板中
tpl.render(context)
# 保存渲染后的Word文檔到指定路徑
tpl.save("output/richtext.docx")

富文本段落

若要精細控制單個段落的樣式,可在代碼中使用RichTextParagraph()RP()對象。此對象需通過{{p <var> }}語法添加至模板。示例代碼如下:

# https://github.com/elapouya/python-docx-template/blob/master/tests/richtextparagraph.py
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")

# 創(chuàng)建富文本段落對象組合不同樣式的段落
rtp = RichTextParagraph()
# 創(chuàng)建富文本對象,用于設置文本的字符樣式
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")  # 數(shù)字編號樣式
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.\aIt 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,
}

# 將上下文數(shù)據(jù)渲染到 Word 模板中
tpl.render(context)
# 保存渲染后的 Word 文檔到指定路徑
tpl.save("output/richtext_paragraph.docx")

浮動對象

圖片插入

可在文檔中動態(tài)插入單張或多張圖片,當前已支持JPEG和PNG格式。只需在模板中使用{{ <var> }}格式的標簽即可。圖片嵌入代碼如下:

myimage = InlineImage(tpl, image_descriptor='test_files/python_logo.png', width=Mm(20), height=Mm(10))

使用時應傳入模板對象與圖片文件路徑,寬高為可選參數(shù)。寬度和高度需通過Mm(毫米)、Inches(英寸)或 Pt(磅)等類進行單位定義。示例代碼如下:

# https://github.com/elapouya/python-docx-template/blob/master/tests/inline_image.py
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")

# 定義渲染模板所需的上下文數(shù)據(jù)
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)
# 使用上下文數(shù)據(jù)和自定義的jinja2環(huán)境渲染W(wǎng)ord模板
tpl.render(context, jinja_env)
tpl.save("output/inline_image.docx")

替換文檔中的圖片

可對文檔中的現(xiàn)有圖片進行替換,具體操作如下:先在模板中插入一張占位圖,按常規(guī)流程渲染模板,之后再將占位圖替換為目標圖片。該方法支持批量處理文檔內的所有媒體文件,且替換后的圖片將維持原占位圖的縱橫比。在模板中插入圖片時,只需指定文件名即可。該替換操作同時對頁眉、頁腳及正文區(qū)域生效。

例如,替換占位圖dummy_header_pic.jpg的語法示例如下:

tpl.replace_pic('dummy_header_pic.jpg', 'header_pic_i_want.jpg')

注意,在將圖片手動插入Word模板時,某些版本的Word會自動對其重命名并存儲。這導致圖片在docx文件內的實際文件名與原文件名完全不同,從而可能引發(fā)找不到圖片的問題。若不確定圖片的具體位置,可將docx文件視為zip壓縮包進行解壓,隨后在word\document.xml文件中,通過查找pic:nvPicPr節(jié)點來定位圖片信息。具體可以參考:python使用docxtpl庫實現(xiàn)圖片替換功能 

在找到目標圖片對應的pic:nvPicPr節(jié)點后,其name屬性的值即為圖片在文檔中實際存儲的文件名。此處的文件名可能不包含圖片格式后綴,替換圖片的示例代碼可能如下:

tpl.replace_pic('Picture 1','header_pic_i_want.jpg')

子文檔

模板變量可包含復雜的子文檔對象,且能通過python-docx的文檔操作方法從零構建。具體步驟為:先從模板對象中獲取子文檔對象,再將其當作python-docx文檔對象使用。該功能需要安裝額外依賴:

pip install "docxtpl[subdoc]"

以下代碼展示了如何創(chuàng)建子文檔,并將該子文檔嵌入到主模板中,最終生成并保存新的文檔:

# https://github.com/elapouya/python-docx-template/blob/master/tests/subdoc.py
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. 創(chuàng)建一個新的子文檔對象
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 :")
# 創(chuàng)建表格(初始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"

# 定義表格數(shù)據(jù)
recordset = ((1, 101, "Spam"), (2, 42, "Eggs"), (3, 631, "Spam,spam, eggs, and ham"))
# 循環(huán)添加數(shù)據(jù)行到表格
for item in recordset:
    row_cells = table.add_row().cells
    row_cells[0].text = str(item[0])  # 數(shù)量(轉為字符串)
    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文件作為子文檔進行合并,如下所示:

# https://github.com/elapouya/python-docx-template/blob/master/tests/merge_docx.py
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")

補充操作

轉義操作

默認情況下,python-docx-template不會對內容進行轉義。這是因為在使用模板語法修改Word文檔時,底層實際上是在處理XML結構,而像<>&這樣的字符在XML中具有特殊含義,必須經過轉義才能正確顯示。以下提供幾種實現(xiàn)轉義的方法:

上下文定義時使用R()包裹內容,模板中添加r標記:

context = { 'var': R('my text') }

模板中寫法:{{r <var> }}

上下文保持原始字符串,模板中使用|e過濾器:

context = { 'var':'my text' }

模板中寫法:{{ <var>|e }}

上下文使用escape()函數(shù)處理內容,模板直接引用:

context = { 'var': escape('my text') }

模板中寫法:{{ <var> }}

調用render方法時啟用自動轉義,默認值為autoescape=False

tpl.render(context, autoescape=True)

在文檔中插入代碼清單時,如果需要同時轉義文本并處理換行符(\n)、段落符(\a)和換頁符(\f),可以在Python代碼中使用Listing類。

例如:

context = { 
    'mylisting': Listing('the listing\nwith\nsome\nlines \a and some paragraph \a and special chars : <>&') 
}

在模板中直接引用即可:

{{ mylisting }}

使用Listing()能夠保持當前字符樣式,除非遇到\a分隔符,它會在該位置開始一個新的段落。

使用示例如下:

# https://github.com/elapouya/python-docx-template/blob/master/tests/escape.py
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\aand some\aother\aparagraphs",
        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\a
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渲染后的特殊字符%、{},可以使用以下方式進行轉義:

  • 顯示%% → 使用{_% %_}
  • 顯示{{ }} → 使用{_{ }_}

獲取未定義變量

要獲取模板渲染時所需的未定義變量,可以按照以下步驟操作:

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 參數(shù),該方法將返回模板中所有需要賦值的變量名的集合。此結果可用于向用戶提示輸入,或寫入文件供后續(xù)手動處理。

Jinja自定義過濾器

Python-docx-template的render方法支持一個可選參數(shù)jinja_env,作為其第二個參數(shù)。通過傳遞自定義的Jinja環(huán)境對象,可以實現(xiàn)自定義過濾器的添加,從而靈活擴展數(shù)據(jù)處理邏輯。以下為具體示例。

模板word內容如下:

=== 姓名展示對比 ===
原始名字: {{ name }}
方法A (Python處理): {{ name_upper }}
方法B (模板過濾器): {{ name|upper }}

對應的Python渲染代碼:

from docxtpl import DocxTemplate
import jinja2

# 準備數(shù)據(jù)
data = {'name': 'zhangsan'}

# Python中處理
data['name_upper'] = data['name'].upper()

# 定義過濾器
def my_upper(text):
    return text.upper()

doc = DocxTemplate("template.docx")

#創(chuàng)建環(huán)境并注冊過濾器
env = jinja2.Environment()
env.filters['upper'] = my_upper 

doc.render(data, env) 
doc.save("output/compare.docx")
print(f"原始數(shù)據(jù): {data['name']}")
print(f"Python處理結果: {data['name_upper']}")
print(f"模板過濾器結果: {data['name'].upper()}")

Microsoft Word 2016特殊行為說明

MS Word 2016會忽略文檔中的制表符,這是該版本特有的情況。類似LibreOffice或WordPad等其他編輯工具則無此問題。同樣,以Jinja2標簽開頭且?guī)в星皩Э崭竦男?,其空格也會被忽略?/p>

為解決上述問題,可使用RichText進行處理:

tpl.render({
    'test_space_r': RichText('          '),
    'test_tabs_r': RichText(5 * '\t'),
})

在模板中,通過{{r ... }}語法調用:

{{r test_space_r}} 空格將被保留
{{r test_tabs_r}} 制表符將正常顯示

到此這篇關于python使用python-docx-template實現(xiàn)模板化Word文檔生成指南的文章就介紹到這了,更多相關python模板化生成Word內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Python字符串中查找子串小技巧

    Python字符串中查找子串小技巧

    這篇文章主要介紹了Python字符串中查找子串小技巧,,需要的朋友可以參考下
    2015-04-04
  • Python NumPy 數(shù)組索引的示例詳解

    Python NumPy 數(shù)組索引的示例詳解

    數(shù)組索引是指使用方括號([])來索引數(shù)組值,numpy提供了比常規(guī)的python序列更多的索引工具,除了按整數(shù)和切片索引之外,數(shù)組可以由整數(shù)數(shù)組索引、布爾索引及花式索引,這篇文章主要介紹了Python NumPy 數(shù)組索引,需要的朋友可以參考下
    2023-01-01
  • Python高效轉換Word表格為Excel的方案全解析

    Python高效轉換Word表格為Excel的方案全解析

    Python通過python-docx庫讀取Word表格,用openpyxl或pandas寫入Excel可自動化完成將Word表格轉為Excel的需要,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下
    2026-02-02
  • pytorch 實現(xiàn)多個Dataloader同時訓練

    pytorch 實現(xiàn)多個Dataloader同時訓練

    這篇文章主要介紹了pytorch 實現(xiàn)多個Dataloader同時訓練的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • Python讀取Ansible?playbooks返回信息示例解析

    Python讀取Ansible?playbooks返回信息示例解析

    這篇文章主要為大家介紹了Python讀取Ansible?playbooks返回信息示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • pyqt5讓圖片自適應QLabel大小上以及移除已顯示的圖片方法

    pyqt5讓圖片自適應QLabel大小上以及移除已顯示的圖片方法

    今天小編就為大家分享一篇pyqt5讓圖片自適應QLabel大小上以及移除已顯示的圖片方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • 使用tqdm顯示Python代碼執(zhí)行進度功能

    使用tqdm顯示Python代碼執(zhí)行進度功能

    在使用Python執(zhí)行一些比較耗時的操作時,為了方便觀察進度,通常使用進度條的方式來可視化呈現(xiàn)。這篇文章主要介紹了使用tqdm顯示Python代碼執(zhí)行進度,需要的朋友可以參考下
    2019-12-12
  • Python3.10安裝圖文教程

    Python3.10安裝圖文教程

    本文主要介紹了Python3.10安裝圖文教程,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • Python操作json數(shù)據(jù)的一個簡單例子

    Python操作json數(shù)據(jù)的一個簡單例子

    這篇文章主要介紹了Python操作json數(shù)據(jù)的一個簡單例子,需要的朋友可以參考下
    2014-04-04
  • 自學python用什么系統(tǒng)好

    自學python用什么系統(tǒng)好

    在本篇文章里小編給大家整理了一篇關于學python用什么系統(tǒng)好的相關文章,有興趣的朋友們可以學習下。
    2020-06-06

最新評論

荔浦县| 司法| 和龙市| 海原县| 宁海县| 沾化县| 北辰区| 土默特左旗| 宁晋县| 延吉市| 衡水市| 将乐县| 互助| 平果县| 仙桃市| 大丰市| 徐闻县| 如皋市| 聂拉木县| 镇巴县| 林甸县| 富宁县| 广宁县| 运城市| 普洱| 德清县| 房产| 高青县| 平昌县| 子长县| 永州市| 墨竹工卡县| 阳曲县| 广灵县| 砀山县| 鄢陵县| 湖州市| 合水县| 财经| 台湾省| 楚雄市|