Hoy os voy a explicar cómo podemos generar un PDF a partir de un HTML y usando FAST API.
Lo primero que vamos a necesitar es instalar las librerías necesarias. En este caso vamos a usar wkhtmltopdf (https://wkhtmltopdf.org/) y PDFKIT de Python (https://pdfkit.org/)
Ahora vamos a instalar wkhtmltopdf, si usamos ubuntu o linux utilizaremos este comando:
apt-get install xvfb libfontconfig wkhtmltopdf -y
Y para instalar PDFKIT:
pip install pdfkit
Una vez instalado, vamos a instalar también un motor de plantillas html Jinja2 (https://palletsprojects.com/p/jinja/). No es necesario hacerlo, ya que podemos generar el HTML con texto plano, pero para mayor facilidad en diseño del PDF recomiendo utilizarlo y seguir las instrucciones.:
pip install -U Jinja2
Una vez instalado, ya tenemos listo el entorno.
Ahora vamos a crear el código. Para ello vamos a crear un objeto auxiliar que realice las operaciones de PDF, lo voy a llamar pdf.py:
import pdfkit from jinja2 import Environment, FileSystemLoader def generarPDF() -> str: env = Environment(loader=FileSystemLoader('.')) # opciones de configuración para wkhtmltopdf options = { 'page-size': 'Letter', 'margin-top': '0.75in', 'margin-right': '0.75in', 'margin-bottom': '0.75in', 'margin-left': '0.75in' } template = env.get_template("templates/template_pdf.html") # define las variables que se van a reemplazar en la plantilla variables = { 'nombre': 'Juan', 'apellido': 'Pérez', 'edad': 30 } html = template.render(variables) return pdfkit.from_string(html, False, options=options)
En este ejemplo tenemos un template_pdf.html que se va a rellenar usando Jinja2 con las variables de ejemplo. Después se transformará a PDF y se devolverá en la función.
Ahora creamos el archivo html dentro de templates/template_pdf.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>PDF Ejemplo Persona</title> </head> <body> <h1>Anexo de alumno</h1> <p>Nombre: {{ nombre }}</p> <p>Apellido: {{ apellido }}</p> <p>Edad: {{ edad }}</p> </body> </html>
Este template, recibe 3 variables (nombre, apellido, edad) y se construirá usando Jinja2.
Ahora creamos un route para obtener el PDF, no voy a crear el código entero, para ello puedes revisar la sección de FastAPI para saber como crear un POST (https://devcodelight.com/crear-un-api-rest-usando-fast-api-ejemplo-sin-conexion-a-base-de-datos/):
from pdf import generarPDF @app.get("/obtener_pdf/", status_code=status.HTTP_200_OK) def create_pdf ( db_session: Session = Depends(get_db)) -> Response: pdf = generarPDF() headers = {'Content-Disposition': 'attachment; filename="data.pdf"'} return Response(pdf, headers=headers, media_type='application/pdf')
Ahora hemos importado la funcion generarPDF desde nuestro objeto: from pdf import generarPDF
Y generamos el pdf, después lo devolvemos como un fichero descargable (attachment) con nombre data.pdf.
Ingeniero en Informática, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.