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, **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:

  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) -> 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 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)

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_context_data(**kwargs) - Provide template context
  • get_context_data_with_docx(docx, **kwargs) - Provide context with DocxTemplate access (for InlineImage, 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.3.0.tar.gz (43.2 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.3.0-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_docxtpl-0.3.0.tar.gz
  • Upload date:
  • Size: 43.2 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.3.0.tar.gz
Algorithm Hash digest
SHA256 2f2a4bacc34609be70f523c7060ea600a87e2807ef899ecd22150222c6e7c1d0
MD5 38ec9d929303886cc0790467201861c1
BLAKE2b-256 4c53814cbc4924567322c6173a59c35a7f1794180d6b86593c9a77a88196104b

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_docxtpl-0.3.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.3.0-py3-none-any.whl.

File metadata

  • Download URL: django_docxtpl-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 17.7 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 52f73b165c67a122c86b2f2b91b4dd9683ca163e81043df52cd6c2f0c042bff4
MD5 4cff27303fe2aa76ae17c0ffe22e061a
BLAKE2b-256 00c298a7a37611c9343c1d86333c7ad9b7165ee8216ee06825eec29889c39260

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_docxtpl-0.3.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