rendering a ReportLab pdf built from SimpleDocTemplate

耗尽温柔 提交于 2021-02-06 10:42:07

问题


I've a got a django app that currently generates pdfs using a canvas that the user can download. I create a StringIO buffer, do some stuff and then send call response.write.

# Set up response
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=menu-%s.pdf' % str(menu_id)
# buffer
buff = StringIO()

# Create the pdf object
p = canvas.Canvas(buff)

# Add some elements... then

p.showPage()
p.save()

# Get the pdf from the buffer and return the response
pdf = buff.getvalue()
buff.close()
response.write(pdf)

I now want to build my pdf using platypus and SimpleDocTemplate and have written this

# Set up response
response = HttpResponse(mimetype='application/pdf')
pdf_name = "menu-%s.pdf" % str(menu_id)
response['Content-Disposition'] = 'attachment; filename=%s' % pdf_name

menu_pdf = SimpleDocTemplate(pdf_name, rightMargin=72,
                            leftMargin=72, topMargin=72, bottomMargin=18)

# container for pdf elements
elements = []

styles=getSampleStyleSheet()
styles.add(ParagraphStyle(name='centered', alignment=TA_CENTER))

# Add the content as before then...

menu_pdf.build(elements)
response.write(menu_pdf)
return response

But this doesn't work, it creates a bad pdf that cannot be opened. I presume the line

response.write(menu_pdf)

is incorrect.

How do I render the pdf?


回答1:


Your error is actually a pretty simple one. It's just a matter of trying to write the wrong thing. In your code, menu_pdf is not a PDF, but a SimpleDocTemplate, and the PDF has been stored in pdf_name, although here I suspect pdf_name is a path name rather than a file object. To fix it, change your code to use a memory file like you did in your original code:

# Set up response
response = HttpResponse(mimetype='application/pdf')
pdf_name = "menu-%s.pdf" % str(menu_id)
response['Content-Disposition'] = 'attachment; filename=%s' % pdf_name

buff = StringIO()

menu_pdf = SimpleDocTemplate(buff, rightMargin=72,
                            leftMargin=72, topMargin=72, bottomMargin=18)

# container for pdf elements
elements = []

styles=getSampleStyleSheet()
styles.add(ParagraphStyle(name='centered', alignment=TA_CENTER))

# Add the content as before then...

menu_pdf.build(elements)
response.write(buff.getvalue())
buff.close()
return response

I'm not sure if using file objects rather than paths with Platypus is mentioned in the documentation, but if you dig into the code you'll see that it is possible.




回答2:


For people who are working with python3 and django 1.7+ some changes to the answer need to be done.

from django.shortcuts import HttpResponse
import io
from reportlab.platypus import SimpleDocTemplate, BaseDocTemplate

def view(request):
    buffer = io.BytesIO()

    doc = # ... create your SimpleDocTemplate / BaseDocTemplate
    # create the usual story
    story = []
    # ...
    doc.build(story)

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=your_name.pdf'
    response.write(buffer.getvalue())
    buffer.close()

    return response


来源:https://stackoverflow.com/questions/5068591/rendering-a-reportlab-pdf-built-from-simpledoctemplate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!