利用 Django 输出 PDFLink to this heading
本文介绍如何用 Django 的视图动态输出 PDF 文件。该功能由绝佳的开源 ReportLab Python PDF 库提供。
动态生成 PDF 文件的优点是你可以为不同的目的创建不同的自定义 PDF——例如,为不同的用户或内容的不同片段生成 PDF。
例如,kusports.com 用 Django 将自定义的,打印友好的 NCAA 锦标赛树状图生成 PDF 文件,发放给参加三月疯狂竞赛的人。
安装 ReportLabLink to this heading
ReportLab 库可从 PyPI 获取。也可以下载 用户指南 (一份 PDF 文件,这不是巧合)。你可以用 pip 安装 ReportLab:
Linux / macOS
$ python -m pip install reportlab
Windows
...\> py -m pip install reportlab
在 Python 交互解释器中导入它,测试你的安装是否成功:
>>> import reportlab
若该命令未抛出任何错误,安装成功。
编写视图Link to this heading
利用 Django 动态生成 PDF 的关键是 ReportLab API 作用于类文件对象,而 Django 的 FileResponse 对象接收类文件对象。
这有个 "Hello World" 示例:
import io
from django.http import FileResponse
from reportlab.pdfgen import canvas
def some_view(request):
# Create a file-like buffer to receive PDF data.
buffer = io.BytesIO()
# Create the PDF object, using the buffer as its "file."
p = canvas.Canvas(buffer)
# 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()
# FileResponse sets the Content-Disposition header so that browsers
# present the option to save the file.
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
代码和注释应该是不言自明的,但是有几件事值得提一下:
响应会自动基于文件扩展名将 MIME 类型设置为应用程序 application/pdf。这告诉浏览器该文档是个 PDF 文件,而不是 HTML 文件或普通的应用程序 application/octet-stream 二进制内容。
将
as_attachment=True传递给FileResponse时,它会设置合适的Content-Disposition头,这将告诉 Web 浏览器弹出一个对话框,提示或确认如何处理该文档,即便设备已配置默认行为。若省略了as_attachment参数,浏览器会用已配置的用于处理 PDF 的程序或插件来处理该 PDF。你也可以提供可选参数
filename。浏览器的“另存为…”对话框会用到它。你可以作为第一个参数传递给
canvas.Canvas的缓冲区也能传递给类FileResponse类来使用 ReportLab API。注意,所有后续生成 PDF 的方法都是在 PDF 对象上调用的(本例中是
p)——而不是在buffer上调用。最后,牢记在 PDF 文件上调用
showPage()和save()。
其它格式Link to this heading
注意,这些例子中没有任何 PDF 特有的数据——只有使用 reportlab 的部分。你可以用类似的技巧生成任意格式,只要你能找到对应的 Python 库。也请看看 利用 Django 输出 CSV,看看另一个例子中,如何用一些技巧输出文本内容。