Django integration for docxtpl - generate documents from Word templates with multi-format export
Project description
django-docxtpl
Django integration for docxtpl - generate documents from Word templates with Jinja2 syntax and export to multiple formats.
Features
- 📝 Generate Word documents (.docx) from templates using Jinja2 syntax
- 📄 Export to multiple formats: DOCX, PDF, ODT, HTML, TXT
- 🔄 Automatic format conversion via LibreOffice headless
- 📑 Update Table of Contents (TOC), charts, and dynamic fields automatically
- 🎯 Simple API with
DocxTemplateResponse - 🏗️ Class-based views with
DocxTemplateViewandDocxTemplateDetailView - ⚡ Automatic file extension based on output format
Installation
pip install django-docxtpl
For PDF and other format conversions, you'll need LibreOffice installed:
# Ubuntu/Debian
sudo apt install libreoffice-core libreoffice-writer
# Ubuntu/Debian (headless server - minimal installation)
sudo apt install libreoffice-core libreoffice-writer-nogui
# macOS
brew install --cask libreoffice
# Alpine Linux (Docker)
apk add libreoffice-writer
# RHEL/CentOS/Fedora
sudo dnf install libreoffice-writer
Quick Start
1. Add to INSTALLED_APPS (optional)
INSTALLED_APPS = [
...
"django_docxtpl",
]
2. Create a Word template
Create a .docx file with Jinja2 placeholders:
Hello {{ name }}!
Your order #{{ order_number }} has been confirmed.
3. Use in your views
Function-based view:
from django_docxtpl import DocxTemplateResponse
def generate_document(request):
context = {
"name": "John Doe",
"order_number": "12345",
}
return DocxTemplateResponse(
request,
template="documents/order.docx",
context=context,
filename="order_confirmation", # Extension added automatically
output_format="pdf", # or "docx", "odt", "html", "txt"
)
Class-based view:
from django_docxtpl import DocxTemplateView
class OrderDocumentView(DocxTemplateView):
template_name = "documents/order.docx"
filename = "order_confirmation"
output_format = "pdf"
def get_context_data(self, **kwargs):
return {
"name": self.request.user.get_full_name(),
"order_number": kwargs.get("order_id"),
}
Detail view for model instances:
from django_docxtpl import DocxTemplateDetailView
class InvoiceDocumentView(DocxTemplateDetailView):
model = Invoice
template_name = "documents/invoice.docx"
output_format = "pdf"
context_object_name = "invoice"
def get_filename(self):
return f"invoice_{self.object.number}"
Configuration
Add these optional settings to your settings.py:
# Directory where your .docx templates are stored
DOCXTPL_TEMPLATE_DIR = BASE_DIR / "docx_templates"
# Path to LibreOffice executable (auto-detected if not set)
DOCXTPL_LIBREOFFICE_PATH = "/usr/bin/soffice"
Supported Output Formats
| Format | Extension | Requires LibreOffice |
|---|---|---|
| DOCX | .docx |
No (Yes if update_fields=True) |
.pdf |
Yes | |
| ODT | .odt |
Yes |
| HTML | .html |
Yes |
| TXT | .txt |
Yes |
Template Syntax
django-docxtpl uses docxtpl which supports full Jinja2 syntax:
{% for item in items %}
- {{ item.name }}: {{ item.price }}€
{% endfor %}
Total: {{ total }}€
{% if discount %}
Discount applied: {{ discount }}%
{% endif %}
See the docxtpl documentation for advanced features like images, tables, and rich text.
Updating TOC and Charts
If your template contains a Table of Contents (TOC), charts, or other dynamic fields that need to be updated after rendering, use the update_fields parameter:
# Function-based view
return DocxTemplateResponse(
request,
template="reports/annual_report.docx",
context=context,
output_format="pdf",
update_fields=True, # Updates TOC, charts, page numbers, etc.
)
# Class-based view
class AnnualReportView(DocxTemplateView):
template_name = "reports/annual_report.docx"
output_format = "pdf"
update_fields = True
Note: This feature requires LibreOffice, even when output format is DOCX.
Working with Images (InlineImage)
To insert images in your documents, use docxtpl's InlineImage. Since it requires access to the DocxTemplate instance, use get_context_data_with_docx() in class-based views or a callable context in function-based views:
Class-based view:
from docxtpl import InlineImage
from docx.shared import Mm
from django_docxtpl import DocxTemplateView
class ReportWithLogoView(DocxTemplateView):
template_name = "reports/report.docx"
output_format = "pdf"
def get_context_data_with_docx(self, docx, **kwargs):
"""Build context with access to DocxTemplate instance."""
return {
"title": "Annual Report",
"logo": InlineImage(docx, "static/logo.png", width=Mm(30)),
}
Function-based view:
from docxtpl import InlineImage
from docx.shared import Mm
from django_docxtpl import DocxTemplateResponse
def report_with_image(request):
def build_context(docx):
return {
"title": "Report",
"logo": InlineImage(docx, "static/logo.png", width=Mm(30)),
}
return DocxTemplateResponse(
request,
template="reports/report.docx",
context=build_context, # Callable receives DocxTemplate instance
output_format="pdf",
)
See the advanced documentation for more examples.
Performance Considerations
Document generation, especially PDF conversion with LibreOffice, can be slow (1-5 seconds per document). For production environments, consider:
- Use a task queue - Offload document generation to background workers using Celery, Django-RQ, or Huey:
Example 1:
# tasks.py (Huey example)
from huey.contrib.djhuey import task
from django.core.files.base import ContentFile
from django_docxtpl.converters import convert_docx
from docxtpl import DocxTemplate
from io import BytesIO
@task()
def generate_report_pdf(report_id):
report = Report.objects.get(pk=report_id)
doc = DocxTemplate("templates/report.docx")
doc.render({"report": report})
buffer = BytesIO()
doc.save(buffer)
buffer.seek(0)
pdf_content = convert_docx(buffer, "pdf", update_fields=True)
# Save to storage, send email, etc.
report.pdf_file.save(f"report_{report_id}.pdf", ContentFile(pdf_content))
Example 2:
# tasks.py (Huey example) - Using render_to_file utility
from huey.contrib.djhuey import task
from django_docxtpl import render_to_file
@task()
def generate_report_to_disk(output_dir, filename, context):
"""Generate a document and save it to disk."""
output_path = render_to_file(
template="reports/monthly.docx",
context=context,
output_dir=output_dir,
filename=filename,
output_format="pdf",
update_fields=True,
)
return str(output_path)
- Serve DOCX when possible - Skip LibreOffice conversion for faster response times
- Cache generated documents - Store frequently requested documents
API Reference
DocxTemplateResponse
DocxTemplateResponse(
request,
template, # Path to .docx template
context=None, # Template context dict or callable(docx) -> dict
filename="document",# Output filename (without extension)
output_format="docx",# Output format
as_attachment=True, # Download as attachment or inline
update_fields=False,# Update TOC, charts, and dynamic fields
)
DocxTemplateView
Class attributes:
template_name- Path to .docx templatefilename- Output filename (default: "document")output_format- Output format (default: "docx")as_attachment- Serve as attachment (default: True)update_fields- Update TOC, charts, and dynamic fields (default: False)
Override methods:
get_template_name()- Dynamic template selectionget_filename()- Dynamic filenameget_output_format()- Dynamic format selectionget_update_fields()- Dynamic field update controlget_context_data(**kwargs)- Provide template contextget_context_data_with_docx(docx, **kwargs)- Provide context with DocxTemplate access (for InlineImage, etc.)
DocxTemplateDetailView
Same as DocxTemplateView plus:
model- Django model classpk_url_kwarg- URL kwarg for primary key (default: "pk")slug_url_kwarg- URL kwarg for slug (default: "slug")slug_field- Model field for slug lookup (default: "slug")context_object_name- Context variable name for object
Error Handling
from django_docxtpl import ConversionError, LibreOfficeNotFoundError
try:
response = DocxTemplateResponse(request, template="doc.docx", output_format="pdf")
except LibreOfficeNotFoundError:
# LibreOffice not installed
pass
except ConversionError as e:
# Conversion failed
pass
Development
# Clone the repository
git clone https://github.com/ctrl-alt-d/django-docxtpl.git
cd django-docxtpl
# Create virtual environment
python -m venv venv
source venv/bin/activate
# Install with development dependencies
pip install flit
flit install -s --deps develop
# Run tests
pytest
# Run linter
ruff check .
# Format code
ruff format .
License
MIT License - see LICENSE for details.
Credits
- docxtpl - Python library for generating docx documents
- python-docx - Python library for Word documents
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_docxtpl-0.4.0.tar.gz.
File metadata
- Download URL: django_docxtpl-0.4.0.tar.gz
- Upload date:
- Size: 44.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
973e5d365f73c2e70fa3e468c71439294608b1a5707dc3040a221ce0f7d73d37
|
|
| MD5 |
0901521ad95be2fd52492007fa2f0993
|
|
| BLAKE2b-256 |
1aba89d55829a1c6d152ba4e0fc6bc545b6ab872479e70f7a27c1f03b82f23cc
|
Provenance
The following attestation bundles were made for django_docxtpl-0.4.0.tar.gz:
Publisher:
publish.yml on ctrl-alt-d/django-docxtpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_docxtpl-0.4.0.tar.gz -
Subject digest:
973e5d365f73c2e70fa3e468c71439294608b1a5707dc3040a221ce0f7d73d37 - Sigstore transparency entry: 767148356
- Sigstore integration time:
-
Permalink:
ctrl-alt-d/django-docxtpl@b5d525a0b58746de8cd3d911b13050ec1fb76653 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ctrl-alt-d
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b5d525a0b58746de8cd3d911b13050ec1fb76653 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_docxtpl-0.4.0-py3-none-any.whl.
File metadata
- Download URL: django_docxtpl-0.4.0-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a764bcdb2cf30c22569d12db739663c6105222595617b49d5f43700be2762db
|
|
| MD5 |
99be5fd61a03b16dc3ff9bc5fbb7c767
|
|
| BLAKE2b-256 |
19c7eafb410c1b9b8646ea0ff5168690a9dfcbaf66334c4dd874c8e00b659a88
|
Provenance
The following attestation bundles were made for django_docxtpl-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on ctrl-alt-d/django-docxtpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_docxtpl-0.4.0-py3-none-any.whl -
Subject digest:
6a764bcdb2cf30c22569d12db739663c6105222595617b49d5f43700be2762db - Sigstore transparency entry: 767148360
- Sigstore integration time:
-
Permalink:
ctrl-alt-d/django-docxtpl@b5d525a0b58746de8cd3d911b13050ec1fb76653 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ctrl-alt-d
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b5d525a0b58746de8cd3d911b13050ec1fb76653 -
Trigger Event:
push
-
Statement type: