呈现从SimpleDocTemplate构建的ReportLab pdf

Ben*_*ths 11 pdf django reportlab

我有一个django应用程序,目前使用用户可以下载的画布生成pdfs.我创建一个StringIO缓冲区,做一些东西,然后发送调用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)
Run Code Online (Sandbox Code Playgroud)

我现在想用platypus和SimpleDocTemplate构建我的pdf并编写了这个

# 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
Run Code Online (Sandbox Code Playgroud)

但这不起作用,它会创建一个无法打开的糟糕pdf.我认为这条线

response.write(menu_pdf)
Run Code Online (Sandbox Code Playgroud)

是不正确的.

如何渲染pdf?

G G*_*III 21

您的错误实际上非常简单.这只是试图写出错误的事情.在你的代码中,menu_pdf不是PDF,而是a SimpleDocTemplate,并且PDF已经存储pdf_name,虽然在这里我怀疑pdf_name是路径名而不是文件对象.要修复它,请更改代码以使用原始代码中的内存文件:

# 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
Run Code Online (Sandbox Code Playgroud)

我不确定在文档中是否提到使用文件对象而不是Platypus的路径,但是如果你深入研究代码,你会发现它是可能的.

  • 您可能想在python3中使用BytesIO而不是StringIO。但除此之外,还要感谢您的出色榜样。 (2认同)

Blo*_*let 6

对于使用 python3 和 django 1.7+ 的人来说,需要对答案进行一些更改。

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
Run Code Online (Sandbox Code Playgroud)