←

WeasyPrint: generar PDFs profesionales desde Markdown con Python

Contexto

Necesitaba generar PDFs de diagnosticos para clientes: portada profesional, headers/footers con numeracion, tablas con estilo, y la posibilidad de escribir el contenido en Markdown para editarlo facil. Las opciones comerciales (PDFKit, reportlab) son complicadas o feas. LaTeX es overkill.

Lo que aprendi

WeasyPrint convierte HTML/CSS a PDF. Combinado con Jinja2 templates y la libreria markdown de Python, el flujo es:

Markdown -> markdown lib -> HTML -> Jinja2 template -> WeasyPrint -> PDF
import markdown
from weasyprint import HTML
from jinja2 import Template

# 1. Markdown a HTML
with open("diagnostico.md") as f:
    content_html = markdown.markdown(f.read(), extensions=["tables"])

# 2. Inyectar en template Jinja2
template = Template(open("plantilla.html").read())
full_html = template.render(
    content=content_html,
    cliente="PROMASL",
    fecha="Marzo 2026",
    tipo="Diagnostico IA",
)

# 3. HTML a PDF
HTML(string=full_html).write_pdf(
    "diagnostico.pdf",
    stylesheets=["estilos.css"],
)

El CSS controla todo: portada con @page :first, headers/footers con @top-left / @bottom-right, saltos de pagina con page-break-before, y numeracion con counter(page).

@page {
    size: letter;
    margin: 25mm 20mm;
    @bottom-right {
        content: "Pagina " counter(page) " de " counter(pages);
        font-size: 9pt;
    }
}
@page :first {
    margin: 0;  /* portada sin margenes */
    @bottom-right { content: none; }
}

Por que importa

El contenido se escribe en Markdown (rapido, git-diffable), los estilos se controlan con CSS (familiar para cualquier dev), y el output es un PDF profesional con portada, numeracion y branding. Sin dependencias pesadas, sin servicios externos.

WeasyPrint necesita libpango y libcairo instalados (apt install libpango-1.0-0 libcairo2), pero despues de eso es pip install weasyprint y listo.