Skip to main content

django-weasyprint-reports

Reportes PDF genéricos para Django: datos → template HTML → WeasyPrint → PDF → HttpResponse.

  • Usa templates normales de Django (sin XML) y WeasyPrint directamente.
  • El PDF se genera bajo demanda en memoria: nunca se guarda en disco, en MEDIA_ROOT ni en la base de datos.
  • No conoce ningún modelo: sirve para cualquiera.
  • Incluye una acción Imprimir para los listados del admin.

Requisitos: Python 3.10+, Django 4.2+, WeasyPrint 70+.

Instalación

pip install django-weasyprint-reports

Desde el repositorio: pip install . (o pip install git+<url-del-repo>).

Añade la app a INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "django.contrib.staticfiles",
    "weasyprint_reports",
]

No tiene modelos ni migraciones, no hace falta migrate.

Dependencias del sistema (Pango)

WeasyPrint necesita la librería Pango del sistema operativo. Sin ella aparece OSError: cannot load library '...libgobject-2.0-0.dll' al generar un PDF. Compruébalo con python -m weasyprint --info.

Ubuntu / Debian

sudo apt install libpango-1.0-0 libpangoft2-1.0-0 libharfbuzz-subset0

macOS

brew install pango

Windows

  1. Instala MSYS2 con las opciones por defecto (C:\msys64).

  2. En el shell MSYS2 UCRT64 ejecuta pacman -S mingw-w64-ucrt-x86_64-pango.

  3. Si usaste la ruta por defecto no hay que hacer nada más: la app la detecta sola. Si instalaste MSYS2 en otro sitio, indícalo en settings.py:

    WEASYPRINT_DLL_DIRECTORIES = r"D:\otra\ruta\ucrt64\bin"
    

La app antepone esa carpeta al PATH antes de importar WeasyPrint, para que sus DLL ganen a las de otros programas (p. ej. Tesseract-OCR, que provoca el error 0x7e).

Sin WeasyPrint o sin Pango el proyecto sigue arrancando; el error aparece solo al generar un PDF.

Más detalles: https://doc.courtbouillon.org/weasyprint/stable/first_steps.html

Uso desde una vista

from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404
from weasyprint_reports.pdf import generar_pdf

@login_required
@permission_required("ventas.view_cliente", raise_exception=True)
def reporte_cliente(request, pk):
    cliente = get_object_or_404(Cliente.objects.prefetch_related("pedidos"), pk=pk)
    return generar_pdf(
        template="ventas/cliente_pdf.html",          # el nombre lo decide el programador
        context={"cliente": cliente},
        filename="cliente.pdf",
        request=request,                          # opcional: habilita request/user en el template
    )

generar_pdf(template, context=None, *, filename="reporte.pdf", request=None, descargar=False) devuelve un HttpResponse. Con descargar=True fuerza la descarga; por defecto se muestra en el navegador. renderizar_pdf(template, context=None, *, request=None) devuelve los bytes (p. ej. para adjuntar a un correo).

Template

{% extends "weasyprint_reports/base.html" %}
{% block header %}Reporte de cliente{% endblock %}
{% block content %}
  <h1>{{ cliente.nombre }}</h1>
  <table>
    <thead><tr><th>Pedido</th><th>Total</th></tr></thead>
    <tbody>
      {% for p in cliente.pedidos.all %}
        <tr><td>{{ p.numero }}</td><td class="num">{{ p.total|floatformat:2 }}</td></tr>
      {% endfor %}
    </tbody>
  </table>
{% endblock %}

weasyprint_reports/base.html define página A4, header y footer repetidos en cada página y "Página X de Y". Bloques disponibles: title, header, footer, extra_css, content, lang. Puedes sobrescribir weasyprint_reports/base.html en tu proyecto para poner tu logotipo, colores, etc.

Imágenes y CSS: usa {% static '...' %} (y MEDIA_URL para archivos subidos). Son los únicos archivos que WeasyPrint puede cargar, además de URIs data:.

Acción "Imprimir" en el admin

from django.contrib import admin
from weasyprint_reports.mixins import ReportAdminMixin

@admin.register(Cliente)
class ClienteAdmin(ReportAdminMixin, admin.ModelAdmin):
    report = True
    list_display = ("nombre", "email", "activo")     # columnas del PDF

En el listado aparece Imprimir en el desplegable de acciones: marcas los registros, pulsas el botón y el PDF se abre en una pestaña nueva (el listado queda como estaba).

Opciones del ModelAdmin:

Atributo Por defecto Descripción
report False Activa la acción.
report_template weasyprint_reports/admin_list.html Template propio; recibe objects y opts.
report_max 500 Máximo de registros por PDF.

Para añadir datos a un template propio sobrescribe get_report_context(self, request, queryset). La acción solo la ven quienes tienen permiso de ver el modelo y solo imprime registros que el admin les permite ver.

Seguridad

  • El nombre del template lo decide siempre el programador, nunca el usuario; no se acepta HTML en bruto.
  • Autoescape de Django activo: no uses |safe ni mark_safe con datos de usuarios.
  • WeasyPrint solo carga archivos de STATIC_URL/MEDIA_URL y URIs data:. Quedan bloqueados http(s) externo (SSRF), file:// y cualquier otro esquema, y se rechaza el path traversal.
  • Nombre de archivo saneado; respuestas con Cache-Control: no-store.
  • Filtra siempre el queryset por lo que el usuario puede ver antes de generar el reporte.
  • Generar PDFs consume CPU: limita la frecuencia si el endpoint queda expuesto.

Tests

python manage.py test weasyprint_reports

Son autocontenidos (usan su propio admin y templates en memoria). Los que usan WeasyPrint real se omiten si no está disponible.

Licencia

Copyright (C) 2026 Hector Leal.

Este software es libre y se distribuye bajo los términos de la GNU Lesser General Public License v3.0 o posterior (LGPL-3.0-or-later). Los textos completos están en los archivos LICENSE (LGPL 3) y COPYING (GPL 3, a la que remite la LGPL).

En la práctica: puedes usar esta librería en proyectos propios o comerciales sin liberar tu código, pero si modificas la propia librería debes publicar esas modificaciones bajo la misma licencia. Esto no es asesoría legal.

Metadata

Release files for django-weasyprint-reports 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-weasyprint-reports 0.1.0
File Size Uploaded Provenance Actions
django_weasyprint_reports-0.1.0.tar.gz 28.7 kB Without provenance Details for django_weasyprint_reports-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-weasyprint-reports 0.1.0
File Interpreter ABI Platform Actions
django_weasyprint_reports-0.1.0-py3-none-any.whl Python 3 none any Details for django_weasyprint_reports-0.1.0-py3-none-any.whl

Total release size: 64.2 kB

Release files / django_weasyprint_reports-0.1.0.tar.gz

Download URL django_weasyprint_reports-0.1.0.tar.gz
Size 28.7 kB
Tags Source
SHA-256 checksum
How to use checksums
177e0e4dc8fa735457e8a4c0aeaaaf416877a5709e7d4ba3ffc9e4c559f7e128
BLAKE2b-256 checksum
How to use checksums
888f853f25809255973394b628d87f6930354d38dfbf683a1e1fd8e1d73ce339
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / django_weasyprint_reports-0.1.0-py3-none-any.whl

Download URL django_weasyprint_reports-0.1.0-py3-none-any.whl
Size 35.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5f8a2de508041c342d8935227cd824e3c27841a41071d647305853d4dad202d2
BLAKE2b-256 checksum
How to use checksums
86ddc0aad75c2f0b59a49bb94fc132d0c2c4b42c9ba15dc0d167c21020757589
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Security for django-weasyprint-reports 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page