Forums

Django - wsgi error - download problem reportlab

hi!

i have a problem i cant solve. I want to download a pdf from report lab, but return this error

Error running WSGI application 2021-03-12 12:18:13,179: AttributeError: 'Canvas' object has no attribute 'read'

This is my view:

from django.http import FileResponse
from reportlab.pdfgen import canvas
from reportlab_qrcode import QRCodeImage
from reportlab.lib.units import mm
from werkzeug.wsgi import FileWrapper


def etichetta_generazione(request,pk):
buffer = io.BytesIO()
etichetta= canvas.Canvas(buffer)
dataqr = 'hello world'

qr = QRCodeImage(dataqr, size=30 * mm)
qr.drawOn(etichetta,0,0)
etichetta.showPage()
etichetta.save()

buffer.seek(0)
w = FileWrapper(etichetta)

return FileResponse(w, as_attachment=True,filename='etichetta.pdf')

Any tips to solve the problem?

Could you share more context of the error? What is the full traceback?

Error running WSGI application

2021-03-15 13:06:42,543: AttributeError: 'Canvas' object has no attribute 'read'

2021-03-15 13:06:42,543: File "/home/Gest3/.virtualenvs/ambientevirtuale/lib/python3.8/site-packages/werkzeug/wsgi.py", line 579, in next

2021-03-15 13:06:42,544: data = self.file.read(self.buffer_size)

This is the complete error. I think is something outside my view

Hi, it looks you're wrapping a canvas object into a FileWrapper which expects file-like object: https://werkzeug.palletsprojects.com/en/1.0.x/wsgi/?highlight=filewrapper#werkzeug.wsgi.FileWrapper.

ok, but i don't figure out how solve the problem.

You need to pass a file-like object, not a canvas.

any tips on how do that?

Your variable buffer is a file-like object, so you can probably just pass it in to the FileWrapper constructor.

ok, i solve the problem. @giles your hint was correct. for the future this is the solution i use:

from django.http import FileResponse
from reportlab.pdfgen import canvas
from reportlab_qrcode import QRCodeImage
from reportlab.lib.units import mm
from werkzeug.wsgi import FileWrapper

Buffer = io.BytesIO()
etichetta = canvas.Canvas(buffer)
#program do stuff
etichetta.showPage
etichetta.save()
buffer.seek(0)
return FileRsponse(FileWrapper(buffer), content_type="application/pdf", as_attachment=True, filename='test.pdf')

Glad to hear that you made it work!

thanks fjl and thanks for the hit you had right