Skip to main content

Django integration for docxtpl - generate documents from Word templates with multi-format export

Project description

django-docxtpl

PyPI version Python Versions Django Versions License: MIT

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 DocxTemplateView and DocxTemplateDetailView
  • ⚡ 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 .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, tmp_dir, **kwargs):
        """Build context with access to DocxTemplate and temp directory."""
        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, tmp_dir):
        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 and tmp_dir Path
        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:

  1. 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)
  1. Serve DOCX when possible - Skip LibreOffice conversion for faster response times
  2. 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, tmp_dir) -> 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
    autoescape=False,   # Enable Jinja2 autoescaping
)

DocxTemplateView

Class attributes:

  • template_name - Path to .docx template
  • filename - 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)
  • autoescape - Enable Jinja2 autoescaping (default: False)

Override methods:

  • get_template_name() - Dynamic template selection
  • get_filename() - Dynamic filename
  • get_output_format() - Dynamic format selection
  • get_update_fields() - Dynamic field update control
  • get_autoescape() - Dynamic autoescape control
  • get_context_data(**kwargs) - Provide template context
  • get_context_data_with_docx(docx, tmp_dir, **kwargs) - Provide context with DocxTemplate and temp directory access (for InlineImage, generated images, etc.)

DocxTemplateDetailView

Same as DocxTemplateView plus:

  • model - Django model class
  • pk_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

django_docxtpl-0.9.0.tar.gz (47.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_docxtpl-0.9.0-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file django_docxtpl-0.9.0.tar.gz.

File metadata

  • Download URL: django_docxtpl-0.9.0.tar.gz
  • Upload date:
  • Size: 47.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_docxtpl-0.9.0.tar.gz
Algorithm Hash digest
SHA256 6a941b49f2115e2155311d084cb650e258354aabb19067623eff546e8fcdeb9c
MD5 ace32611d21766eeeaf9d7a576578200
BLAKE2b-256 563d30a36afdcce6bfa2408066cb316c34e731181678e8885d1ccf6f5bab8f9c

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_docxtpl-0.9.0.tar.gz:

Publisher: publish.yml on ctrl-alt-d/django-docxtpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_docxtpl-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: django_docxtpl-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 19.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_docxtpl-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8870f63f21d57d68cb8ad75b357a52f679661e7e46d5dd02112754517c80727a
MD5 4f90b1e31d4ffac483dccbe70715f47e
BLAKE2b-256 75f53a8404de01b71faf317dbe249a207608024aa7f5d2f224e5b97009e08ea8

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_docxtpl-0.9.0-py3-none-any.whl:

Publisher: publish.yml on ctrl-alt-d/django-docxtpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page