El Formato Portable de Documentos (PDF, por Portable Document Format) es un formato desarrollado por Adobe que es usado para representar documentos imprimibles, completos con formato perfecto hasta un nivel de detalle medido en pixels, tipografías empotradas y gráficos de vectores en 2D. Puedes pensar en un documento PDF como el equivalente digital de un documento impreso; efectivamente, los PDFs se usan normalmente cuando se necesita entregar un documento a alguien para que lo imprima.
Puedes generar PDFs fácilmente con Python y Django gracias a la excelente librería de software libre ReportLab. La ventaja de generar ficheros PDFs dinámicamente es que puedes crear PDFs a medida para diferentes propósitos — supongamos, para diferentes usuarios u diferentes contenidos.
Por ejemplo, hemos usado Django y ReportLab en KUSports.com para generar programas de torneos de la NCAA personalizados, listos para ser impresos.
11.3.1. Instalar ReportLab
Antes de que puedas generar ningún PDF, deberás instalar ReportLab. Este paso es muy sencillo, ya que solamente debes descargar la librería en el sitio reportlab.org/downloads.html.
La guía del usuario, que solamente está disponible en formato PDF, contiene instrucciones de instalación adicionales.
Nota Si estás usando una distribución moderna de Linux, podrías desear comprobar con la utilidad de manejo de paquetes de software antes de instalar ReportLab. La mayoría de los repositorios de paquetes ya incluyen ReportLab.
Por ejemplo, si estás usando la (excelente) distribución Ubuntu, un simple
apt-get install python-reportlab
hará la magia necesaria.
Prueba tu instalación importando la misma en el intérprete interactivo Python:
>>> import reportlab
Si ese comando no lanza ningún error, la instalación funcionó.
11.3.2. Escribir tu Vista
Del mismo modo que CSV, la generación de PDFs en forma dinámica con Django es sencilla porque la API ReportLab actúa sobre objetos similares a ficheros (file-like según la jerga Python).
A continuación un ejemplo "Hola Mundo":
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
Son necesarias alguna notas:
- Usamos el tipo MIME
application/pdf
. Esto le indica al navegador que el documento es un fichero PDF y no un fichero HTML. Si no incluyes esta información, los navegadores web probablemente interpretarán la respuesta como HTML, lo que resultará en jeroglíficos en la ventana del navegador. - Interactuar con la API ReportLab es sencillo: sólo pasa
response
como el primer argumento acanvas.Canvas
. La claseCanvas
espera un objeto file-like, y los objetosHttpResponse
se ajustarán a la norma. - Todos los métodos de generación de PDF subsecuentes son llamados
pasándoles el objeto PDF (en este caso
p
), noresponse
. - Finalmente, es importante llamar a los métodos
showPage()
ysave()
del objeto PDF (de otra manera obtendrás un fichero PDF corrupto).
11.3.3. PDFs complejos
Si estás creando un documento PDF complejo (o cualquier pieza de datos de gran
tamaño), considera usar la librería cStringIO
como un lugar de
almacenamiento temporario para tu fichero PDF. La librería cStringIO
provee una interfaz vía objetos file-like que está escrita en C para máxima
eficiencia.
Ese es el ejemplo "Hola Mundo" anterior modificado para usar cStringIO
:
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response