Use a docx as a jinja2 template
—
Functionality for inserting images, composing sub-documents, and handling text with special characters within templates. These capabilities enable complex document assembly and rich media integration.
Class for generating inline images in templates with precise control over dimensions and positioning.
class InlineImage:
def __init__(self, tpl, image_descriptor, width=None, height=None, anchor=None):
"""
Initialize InlineImage for insertion into template.
Parameters:
- tpl: DocxTemplate instance reference
- image_descriptor: Path to image file or file-like object
- width: Image width (in EMUs, inches, or Inches() object)
- height: Image height (in EMUs, inches, or Inches() object)
- anchor: Optional URL anchor for image hyperlink
"""Access to image configuration and template reference.
@property
def tpl:
"""Reference to DocxTemplate instance."""
@property
def image_descriptor:
"""Path or file-like object for image source."""
@property
def width:
"""Image width dimension."""
@property
def height:
"""Image height dimension."""
@property
def anchor:
"""URL anchor for hyperlink (optional)."""Methods for converting image to XML representation for template insertion.
def __str__(self) -> str:
"""Return XML representation of inline image."""
def __unicode__(self) -> str:
"""Return Unicode XML representation of inline image."""
def __html__(self) -> str:
"""Return HTML-like representation of inline image."""Class for sub-documents that can be inserted into master documents, enabling complex document composition and modular content assembly.
class Subdoc:
def __init__(self, tpl, docpath=None):
"""
Initialize Subdoc for document composition.
Parameters:
- tpl: DocxTemplate instance reference
- docpath: Optional path to existing document to use as base
"""Access to document instances and template reference.
@property
def tpl:
"""Reference to DocxTemplate instance."""
@property
def docx:
"""Main document reference."""
@property
def subdocx:
"""Sub-document instance."""The Subdoc class delegates to python-docx Document methods via __getattr__, providing access to all document creation capabilities:
# Document content creation methods (delegated to python-docx)
def add_paragraph(self, text='', style=None): ...
def add_table(self, rows, cols, style=None): ...
def add_picture(self, image_path_or_stream, width=None, height=None): ...
def add_heading(self, text='', level=1): ...
def add_page_break(self): ...
# ... and all other python-docx Document methodsMethods for converting subdocument to XML representation for template insertion.
def __str__(self) -> str:
"""Return XML representation of subdocument."""
def __unicode__(self) -> str:
"""Return Unicode XML representation of subdocument."""
def __html__(self) -> str:
"""Return HTML-like representation of subdocument."""Class for managing text with newlines and special characters while preserving template styling. Useful for code listings, addresses, and multi-line formatted text.
class Listing:
def __init__(self, text):
"""
Initialize Listing with text content.
Parameters:
- text: Text content with newlines and special characters
"""Methods for converting listing to escaped XML representation.
def __str__(self) -> str:
"""Return escaped XML representation of listing text."""
def __unicode__(self) -> str:
"""Return Unicode escaped XML representation of listing text."""
def __html__(self) -> str:
"""Return HTML-like representation of listing text."""from docxtpl import DocxTemplate, InlineImage
from docx.shared import Inches
doc = DocxTemplate("template.docx")
# Create inline image with specific dimensions
logo = InlineImage(doc, "company_logo.png", width=Inches(2), height=Inches(1))
# Image with hyperlink
chart_url = doc.build_url_id("https://example.com/chart-details")
chart = InlineImage(doc, "sales_chart.png", width=Inches(4), height=Inches(3), anchor=chart_url)
context = {
'company_logo': logo,
'sales_chart': chart
}
doc.render(context)
doc.save("report_with_images.docx")from docxtpl import DocxTemplate, InlineImage
from docx.shared import Inches, Cm
doc = DocxTemplate("gallery_template.docx")
# Different image sizes
images = []
image_files = ["photo1.jpg", "photo2.jpg", "photo3.jpg"]
sizes = [Inches(2), Cm(5), Inches(1.5)]
for img_file, size in zip(image_files, sizes):
img = InlineImage(doc, img_file, width=size, height=size)
images.append(img)
context = {
'gallery_images': images
}
doc.render(context)
doc.save("photo_gallery.docx")from docxtpl import DocxTemplate, Subdoc
doc = DocxTemplate("main_template.docx")
# Create subdocument with content
subdoc = doc.new_subdoc()
# Add content to subdocument using python-docx methods
subdoc.add_heading("Technical Specifications", level=2)
subdoc.add_paragraph("This section contains detailed specifications.")
# Create table in subdocument
table = subdoc.add_table(rows=3, cols=2)
table.cell(0, 0).text = "Component"
table.cell(0, 1).text = "Value"
table.cell(1, 0).text = "CPU"
table.cell(1, 1).text = "Intel i7"
table.cell(2, 0).text = "RAM"
table.cell(2, 1).text = "16GB"
context = {
'technical_details': subdoc
}
doc.render(context)
doc.save("complete_document.docx")from docxtpl import DocxTemplate, Subdoc, InlineImage
from docx.shared import Inches
doc = DocxTemplate("complex_template.docx")
# Create multiple subdocuments
intro_section = doc.new_subdoc()
intro_section.add_heading("Introduction", level=1)
intro_section.add_paragraph("This document presents our quarterly analysis.")
results_section = doc.new_subdoc()
results_section.add_heading("Results", level=1)
results_section.add_paragraph("Key findings from our analysis:")
# Add image to results section
chart_img = InlineImage(doc, "quarterly_chart.png", width=Inches(5))
results_section.add_paragraph().add_run().add_picture(chart_img.image_descriptor)
context = {
'introduction': intro_section,
'results': results_section,
'executive_signature': InlineImage(doc, "signature.png", width=Inches(2))
}
doc.render(context)
doc.save("quarterly_report.docx")from docxtpl import DocxTemplate, Listing
doc = DocxTemplate("code_template.docx")
# Code listing with proper formatting
python_code = Listing("""def calculate_total(items):
total = 0
for item in items:
total += item['price'] * item['quantity']
return total
# Example usage
items = [
{'name': 'Widget', 'price': 10.00, 'quantity': 5},
{'name': 'Gadget', 'price': 25.00, 'quantity': 2}
]
result = calculate_total(items)""")
# Address with line breaks
address = Listing("""John Doe
123 Main Street
Apartment 4B
New York, NY 10001
United States""")
# Text with special characters
special_text = Listing("Special chars: < > & \" ' \n\nNew line after special chars")
context = {
'code_example': python_code,
'customer_address': address,
'notes': special_text
}
doc.render(context)
doc.save("formatted_document.docx")from docxtpl import DocxTemplate, InlineImage, Subdoc, Listing, RichText
from docx.shared import Inches
doc = DocxTemplate("mixed_media_template.docx")
# Header image
header_img = InlineImage(doc, "header_banner.png", width=Inches(6))
# Rich text introduction
intro = RichText()
intro.add("Welcome to our ", bold=False)
intro.add("Annual Report 2024", bold=True, color="0066CC", size=14)
# Code listing
sample_code = Listing("""# Configuration
SERVER_URL = "https://api.example.com"
API_KEY = "your-api-key-here"
TIMEOUT = 30""")
# Subdocument with mixed content
details = doc.new_subdoc()
details.add_heading("Technical Details", level=2)
details.add_paragraph("Architecture overview:")
arch_img = InlineImage(doc, "architecture_diagram.png", width=Inches(4))
details.add_paragraph("System Architecture").add_run()._element.append(arch_img._element)
context = {
'header_banner': header_img,
'introduction': intro,
'configuration': sample_code,
'technical_section': details
}
doc.render(context)
doc.save("mixed_media_report.docx")Install with Tessl CLI
npx tessl i tessl/pypi-docxtpl