рендеринг pdf-файла ReportLab, построенного из SimpleDocTemplate

у меня есть приложение django, которое в настоящее время генерирует PDF-файлы, используя холст, который пользователь может скачать. Я создаю буфер StringIO, делаю некоторые вещи, а затем отправляю ответ на вызов.писать.

# 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)

Теперь я хочу построить свой pdf с помощью утконоса и SimpleDocTemplate и написал это

# 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

но это не работает, он создает плохой pdf, который не может быть открыт. Я предполагаю, что линия

response.write(menu_pdf)

- это неправильно.

как я представляю формат PDF?

1 ответов


ваша ошибка на самом деле довольно проста. Это просто попытка написать что-то не то. В коде menu_pdf не PDF, а 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

Я не уверен, что использование файловых объектов, а не путей с утконосом упоминается в документации, но если вы покопаетесь в коде, то увидите, что это возможно.