Dibuja imágenes con canvas y usa SimpleDocTemplate

Estoy escribiendo archivos PDF con reportlab dentro de una vista de django, son muy simples, el encabezado, el contenido y el pie de página.

Estoy usando SimpleDocTemplate, que encaja muy bien, para dibujar tablas en el contenido, el pie de página y el encabezado están utilizando:

build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame). 

Mi pregunta es, ¿cómo puedo dibujar una imagen como usar Canvas.drawImage (…)? Necesito una imagen “flotante” … colocada sobre el texto donde quiero, y con SimpleDocTemplate no tengo un objeto Canvas para hacer esto.

Buscando he encontrado esto:

El diseño de Platypus utiliza materiales fluidos. Los empacadores normalmente establecen el atributo canv en cada fluido cuando se envuelve, divide o dibuja, es decir, alrededor de los métodos de envoltura, división y dibujo. Dentro de esos métodos tienes acceso al canvas usando el atributo canv de self.

¿Cómo se puede utilizar esto?

Ummmm, más cosas para probar:

 flowables.Macro flowables.CallerMacro 
 # - * - encoding: utf-8 - * -
 desde reportlab.lib.pagesizes importar A4, horizontal, vertical
 desde reportlab.lib.styles import getSampleStyleSheet
 de reportlab.platypus import Table, Flowable, SimpleDocTemplate, Paragraph, Spacer, Image
 desde reportlab.lib importar texto aleatorio
 de reportlab import platypus

 import os, al azar

 styles = getSampleStyleSheet ()
 ruta = os.path.realpath (os.path.dirname (__ archivo__))

 def drawPageFrame (canvas, doc):
     canvas.saveState ()
     canvas.drawImage (ruta + "/ ujiPDF.jpg", 50,50,57,57)
     canvas.restreState ()

 doc = SimpleDocTemplate ("salida.pdf", tamaño de página = A4)

 elementos = []

 com = 'canvas.drawImage ("' + ruta + '/ ujiPDF.jpg", 100,100,57,57)'
 imprimir com
 elementos.append (platypus.flowables.Macro ('canvas.saveState ()'))
 imprimir platypus.flowables.Macro (com)
 elementos.append (platypus.flowables.Macro (com))
 elementos.append (platypus.flowables.Macro ('canvas.restreState ()'))

 para = Párrafo (randomtext.randomText (randomtext.PYTHON, 20), estilos ["Normal"])
 elementos.append (para)

 doc.build (elementos, onFirstPage = drawPageFrame, onLaterPages = drawPageFrame)

Este es el enfoque Macro … salida limpia pero sin la segunda imagen.

Su mejor opción es crear una subclase de SimpleDocTemplate o BaseDocTemplate. En el método de construcción tendrás acceso al canvas. Si desea aprovechar todo lo que hace SimpleDocTemplate, puede intentar copiarlo directamente desde site-packages/reportlab/platypus/doctemplate.py .

Hay clase de imagen en el ornitorrinco. Solo use from reportlab.platypus import Image y from reportlab.platypus import Image acceso a esta clase. Funciona como otras clases dentro y smth.append(Image(filename)) anexa la imagen al objeto que necesita para construir en pdf. Fundada en el sitio web personal de Tyler Lessman.

No es necesario crear una subclase de la plantilla del documento completo, si lo entiendo bien, solo desea un elemento fluido que pueda colocar en una plantilla SimpleDoc. Puedes lograrlo con una subclase muy fácil de Flowable.

-> En particular, dado que las personas a menudo preguntan cómo colocar objetos matplotlib en reportlab, les mostraré cómo generar un gráfico con matplotlib y luego usaré el flowable modificado para colocar ese gráfico en una plantilla SimpleDoc (sin guardar el archivo en el disco). El concepto se aplica a cualquier archivo o cualquier cosa que pueda introducir en un cStringIO

-> El siguiente SÍ le permite colocar la figura sobre el texto (cambie la altura de negativa a positiva para empujarla por encima de la línea imaginaria en la parte superior de la sección en la que se encuentra el gráfico)

El concepto clave es que cada Flowable también contiene un canvas al que podemos dibujar.

 import matplotlib.pyplot as plt import cStringIO from reportlab.lib.units import inch, cm from reportlab.lib.pagesizes import letter from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, Table from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle import reportlab.lib, reportlab.platypus class flowable_fig(reportlab.platypus.Flowable): def __init__(self, imgdata): reportlab.platypus.Flowable.__init__(self) self.img = reportlab.lib.utils.ImageReader(imgdata) def draw(self): self.canv.drawImage(self.img, 0, 0, height = -2*inch, width=4*inch) # http://www.reportlab.com/apis/reportlab/2.4/pdfgen.html doc = SimpleDocTemplate(("report.pdf"),pagesize=letter, rightMargin=72,leftMargin=72, topMargin=72,bottomMargin=18) Story=[] styles=getSampleStyleSheet() ptext = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi massa dolor, vulputate quis elit sed, sagittis consectetur erat. Sed lobortis nisi eros, eu maximus enim iaculis ac. Vestibulum sagittis urna nec interdum aliquam. Pellentesque ornare velit ut ante ullamcorper, vulputate accumsan nisi vulputate. Fusce consectetur dolor quam. Phasellus hendrerit, ligula vel consectetur pretium, lorem neque dapibus eros, ornare suscipit ipsum dolor id nisl. Sed vel orci id leo efficitur lobortis sit amet id risus. Nullam euismod, ipsum a posuere scelerisque, ante lorem ultrices nibh, ut feugiat metus ex congue enim. Nam lobortis, metus id pellentesque feugiat, arcu orci rutrum felis, quis luctus urna nisl at nulla. Donec eu eros pharetra dolor congue facilisis at ac magna. Nullam eu ultricies metus. Sed sodales, libero viverra pellentesque tempus, magna purus convallis nibh, eu condimentum tortor erat tincidunt turpis. Vestibulum scelerisque tincidunt egestas. Nullam commodo diam nisl, sed consequat ex sagittis eu.' Story.append(Paragraph(ptext, styles["Normal"])) fig = plt.figure(figsize=(10, 3)) plt.plot([1,2,3,4]) plt.ylabel('This is a boring plot') imgdata = cStringIO.StringIO() fig.savefig(imgdata, format='png') imgdata.seek(0) # rewind the data pic = flowable_fig(imgdata) Story.append(pic) doc.build(Story)