Saltar a contenido

WeasyPrint

WeasyPrint es un paquete Python que permite generar ficheros PDF. Pensado especialmente para entornos de desarrollo, convierte ficheros HTML en formato PDF.

Instalación

La instalación del paquete es muy sencilla:

$ pip install weasyprint
$ uv add weasyprint

Requisitos del sistema

Este paquete necesita ciertas dependencias de sistema para su correcto funcionamiento:

$ sudo apt-get install -y libglib2.0-0 libpango-1.0-0 libpangoft2-1.0-0
$ brew install pango glib
Enlaces simbólicos

Si aparecen problemas, es posible que haya que realizar algunos ajustes de enlaces simbólicos:

sudo ln -s /opt/homebrew/opt/glib/lib/libgobject-2.0.0.dylib /usr/local/lib/gobject-2.0
sudo ln -s /opt/homebrew/opt/pango/lib/libpango-1.0.dylib /usr/local/lib/pango-1.0
sudo ln -s /opt/homebrew/opt/harfbuzz/lib/libharfbuzz.dylib /usr/local/lib/harfbuzz
sudo ln -s /opt/homebrew/opt/fontconfig/lib/libfontconfig.1.dylib /usr/local/lib/fontconfig-1
sudo ln -s /opt/homebrew/opt/pango/lib/libpangoft2-1.0.dylib /usr/local/lib/pangoft2-1.0

Modo de uso

Aunque existen otros casos de uso, aquí cubriremos el más habitual. Partiendo de un fichero HTML lo convertiremos a PDF.

Para ello vamos a hacer uso de la clase HTML que proporciona WeasyPrint:

>>> from weasyprint import HTML#(1)!

>>> html_content = """
... <h1>This is WeasyPrint</h1>
... <p>A powerfull package to generate PDF from HTML</p>
... """#(2)!

>>> HTML(string=html_content).write_pdf('report.pdf')#(3)!

  1. Importamos la clase HTML.
  2. Creamos una cadena de texto con código HTML.
    • El parámetro string nos permite pasar una cadena de texto.
    • Usamos el método write_pdf() para generar el PDF de salida, indicando su ruta.

>>> from weasyprint import HTML#(1)!

>>> !cat report.html#(2)!
<h1>This is WeasyPrint</h1>
<p>A powerfull package to generate PDF from HTML</p>

>>> HTML('report.html').write_pdf('report.pdf')#(3)!

  1. Importamos la clase HTML.
  2. Partimos de un fichero de texto ya creado.
    • Cuando utilizamos un parámetro posicional WeasyPrint trata de averiguar si se trata de un nombre de fichero, de una URL absoluta o de un file object.
    • Usamos el método write_pdf() para generar el PDF de salida, indicando su ruta.

Hojas de estilo

Nada impide que incorporemos a nuestro «informe» estilos CSS para añadir una mejor presentación:

report.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="report.css">
  <title>WeasyPrint</title>
</head>
<body>
  <h1>This is WeasyPrint</h1>
  <p>A powerfull package to generate PDF from HTML</p>
</body>
</html> 
report.css
body {
  color: lightblue;
} 
>>> from weasyprint import HTML

>>> HTML('report.html').write_pdf('report.pdf')

URL base

Si queremos usar rutas relativas dentro del fichero HTML y no son relativas a la carpeta «actual» de trabajo, hay que especificarlo utilizando el parámetro base_url que pasaremos al constructor de la clase HTML.

Su uso depende del tipo de aplicación que estemos desarrolando:

>>> from weasyprint import HTML

>>> base_url = f'file://{absolute_path_to_assets}/'#(1)!
>>> HTML('input.html', base_url=base_url).write_pdf('output.pdf')

  1. Fundamental acabar la ruta con barra /

>>> from weasyprint import HTML

>>> base_url = f'http://{absolute_path_to_assets}/'#(1)!
>>> HTML('input.html', base_url=base_url).write_pdf('output.pdf')

  1. Fundamental acabar la ruta con barra /

Django

En Django podemos utilizar la función request.build_absolute_uri() para este cometido:

views.py
from weasyprint import HTML

def make_report(request):
    HTML('input.html', base_url=request.build_absolute_uri()).write_pdf('output.pdf')