生成 PDF 文件
便携文档格式 (PDF) 是由 Adobe 开发的格式,主要用于呈现可打印的文档,其中包含有 pixel-perfect 格式,嵌入字体以及2D矢量图像。你完全可以将PDF文档看成纸质打印文档的数字版本,它在出版发行领域使用非常广泛。
可以方便的使用 Python和Django生成PDF文档需要归功于一个出色的开源库, ReportLab (http://www.reportlab.org/rl_toolkit.html) 。动态生成 PDF 文件的好处是在不同的情况下,如不同的用户或者不同的内容,可以按需生成不同的 PDF 文件。
下面的例子是使用 Django 和 ReportLab 在 KUSports.com 上生成个性化的可打印的 NCAA 赛程表 (tournament brackets) 。
安装 ReportLab
在生成 PDF 文件之前,需要安装ReportLab库。这通常是个很简单的过程:从下面的地址下载并安装这个库即可。 http://www.reportlab.org/downloads.html.
注意
如果使用的是一些新的 Linux 发行版,则在安装前可以先检查包管理软件。多数软件包仓库中都加入了 ReportLab 。
比如,如果使用 Ubuntu 发行版,只需要简单的 apt-get install python-reportlab
一行命令即可完成安装。
使用手册(原始的只有PDF格式)可以从http://www.reportlab.org/rsrc/userguide.pdf 下载,其中包含有一些其它的安装指南。
在 Python 交互环境中导入这个软件包以检查安装是否成功。
>>> import reportlab
如果刚才那条命令没有出现任何错误,则表明安装成功。
编写视图
和 CSV 类似,由 Django 动态生成 PDF 文件很简单,因为 ReportLab API 同样可以使用类似文件对象。
下面是一个 "Hello World" 的示例:
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
需要注意以下几点:
- 这里我们使用的 MIME 类型是
application/pdf
。这会告诉浏览器这个文档是一个 PDF 文档,而不是 HTML 文档。如果忽略了这个参数,浏览器可能会把这个文件看成 HTML 文档,这会使浏览器的窗口中出现很奇怪的文字。 - 使用 ReportLab 的 API 很简单:只需要将
response
对象作为canvas.Canvas
的第一个参数传入。 - 所有后续的PDF生成方法需要由PDF对象调用(在本例中是
p
),而不是response
对象。 - 最后需要对PDF文件调用
showPage()
和save()
方法(否则你会得到一个损坏的PDF文件)。
复杂的 PDF 文件
如果您在创建一个复杂的 PDF 文档(或者任何较大的数据块),请使用 cStringIO
库存放临时生成的 PDF 文件。 cStringIO
提供了一个用 C 编写的类似文件对象的接口,从而可以使系统的效率最高。
下面是使用 cStringIO
重写的 "Hello World" 例子:
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response
{$ activeFileHint $}