Tal como había mencionado en el post pasado el proyecto en el que estoy trabajando en el Google App Engine requiere la generación de documentos en formato PDF dinámicamente. En java alguna vez use iText y me pareció una muy buena librería con un API bastante flexible y poderoso. Siendo nuevo en python, decidí buscar proyectos open source similares que resolvieran esta problematica y tratar de entender cómo lo hacen.
El primero que encontré y el más popular fue ReportLab seguido de un tutorial bastate básico (lo que nosotros llamamos el "Hola Mundo") de como usarlo, ya que los ejemplos incluidos en la distribución son muy complejos de entender para un principiante como yo. Así que decidí intentar extrapolando los conceptos del tutorial a mi proyecto con tan mala suerte que todo terminó en una excepción de entrada/salida. Despues de leer cuidadosamente el stack-trace me dí cuenta que estaba trantando de acceder al sistema de archivos, operación específica que restringe el app engine.
Aprovechando que en el mismo proyecto uso Django como framework para el desarrollo de mi aplicación decidí incluirlo como un término de la búsqueda, de esta manera encontré esta página de documentación que fue clave en la solucion del problema ya que trataba al request HTTP como un archivo. Hice los ajustes necesarios al código fuente y probé, con tan mala suerte que me volvió a salir una vez más una excepcion de entrada/salida. Muy extraño, no? Ante la frustración decidí escribir en el Google Group la pregunta y de paso ver si alguien ya había resuelto este problema antes.
Antes de recibir cualquier respuesta y apelando al escepticismo de que todo el conocimiento está en el Group decidí incluir app engine como término de búsqueda, inesperadamente encontré exactamente lo que necesitaba. Luego de algunas pruebas y de identificar el gran error que había cometido la generación del archivo PDF fue exitosa. Ahora les presento el código fuente:
import cgi
import wsgiref.handlers
import logging
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
import os
from google.appengine.ext.webapp import template
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import cm, mm, inch, pica
class FinHandler(webapp.RequestHandler):
def get(self):
# Crea el objeto HttpResponse con sus encabezados apropiados
self.response.headers['Content-Type'] = 'application/pdf'
self.response.headers['Content-Disposition'] = 'attachment; filename=archivo.pdf'
# Crea el documento PDF usando el pedido como "archivo" y de tamaño carta
p = canvas.Canvas(self.response.out, pagesize = letter)
y = 750
# Escribe el titulo
p.drawCentredString(letter[0] / 2, y, "titulo")
....
#Salto de pagina
p.showPage()
#Guarda y limpia el documento PDF
p.save()
lunes, 12 de mayo de 2008
PDFs en Google App Engine
Suscribirse a:
Enviar comentarios (Atom)


2 comentarios:
muy interesante, gracias por postear el código fuente, quizás me sirva...
yo ando a la búsqueda de algún módulo que me permita generar archivos ZIP con farios ficheros CSV a partir de tablas del datastore (algo así como una exportación a CSV de la base de datos completa)
Saludos
Excelente entrada, muy interesante la manera de tratar el stream de la request como fichero de salida, supongo que futuros problemas relacionados se solucionaran igual. Por cierto, critica constructiva, usa la etiqueta PRE para formatear el codigo, te respetará los espacios en blanco. :)
Publicar un comentario en la entrada