利用Python的Django框架生成PDF文件的教程
便携文档格式(PDF)是由Adobe开发的格式,主要用于呈现可打印的文档,其中包含有pixel-perfect格式,嵌入字体以及2D矢量图像。YoucanthinkofaPDFdocumentasthedigitalequivalentofaprinteddocument;indeed,PDFsareoftenusedindistributingdocumentsforthepurposeofprintingthem.
可以方便的使用Python和Django生成PDF文档需要归功于一个出色的开源库,ReportLab(http://www.reportlab.org/rl_toolkit.html)。动态生成PDF文件的好处是在不同的情况下,如不同的用户或者不同的内容,可以按需生成不同的PDF文件。TheadvantageofgeneratingPDFfilesdynamicallyisthatyoucancreatecustomizedPDFsfordifferentpurposessay,fordifferentusersordifferentpiecesofcontent.
下面的例子是使用Django和ReportLab在KUSports.com上生成个性化的可打印的NCAA赛程表(tournamentbrackets)。
安装ReportLab
在生成PDF文件之前,需要安装ReportLab库。这通常是个很简单的过程:Itsusuallysimple:justdownloadandinstallthelibraryfromhttp://www.reportlab.org/downloads.html.
Note
如果使用的是一些新的Linux发行版,则在安装前可以先检查包管理软件。多数软件包仓库中都加入了ReportLab。
比如,如果使用(杰出的)Ubuntu发行版,只需要简单的apt-getinstallpython-reportlab一行命令即可完成安装。
使用手册(原始的只有PDF格式)可以从http://www.reportlab.org/rsrc/userguide.pdf下载,其中包含有一些其它的安装指南。
在Python交互环境中导入这个软件包以检查安装是否成功。
>>>importreportlab
如果刚才那条命令没有出现任何错误,则表明安装成功。
编写视图
和CSV类似,由Django动态生成PDF文件很简单,因为ReportLabAPI同样可以使用类似文件对象。
下面是一个HelloWorld的示例:
fromreportlab.pdfgenimportcanvas fromdjango.httpimportHttpResponse defhello_pdf(request): #CreatetheHttpResponseobjectwiththeappropriatePDFheaders. response=HttpResponse(mimetype='application/pdf') response['Content-Disposition']='attachment;filename=hello.pdf' #CreatethePDFobject,usingtheresponseobjectasits"file." p=canvas.Canvas(response) #DrawthingsonthePDF.Here'swherethePDFgenerationhappens. #SeetheReportLabdocumentationforthefulllistoffunctionality. p.drawString(100,100,"Helloworld.") #ClosethePDFobjectcleanly,andwe'redone. p.showPage() p.save() returnresponse
需要注意以下几点:
这里我们使用的MIME类型是application/pdf。这会告诉浏览器这个文档是一个PDF文档,而不是HTML文档。如果忽略了这个参数,浏览器可能会把这个文件看成HTML文档,这会使浏览器的窗口中出现很奇怪的文字。Ifyouleaveoffthisinformation,browserswillprobablyinterprettheresponseasHTML,whichwillresultinscarygobbledygookinthebrowserwindow.
使用ReportLab的API很简单:只需要将response对象作为canvas.Canvas的第一个参数传入。
所有后续的PDF生成方法需要由PDF对象调用(在本例中是p),而不是response对象。
最后需要对PDF文件调用showPage()和save()方法(否则你会得到一个损坏的PDF文件)。
复杂的PDF文件
如果您在创建一个复杂的PDF文档(或者任何较大的数据块),请使用cStringIO库存放临时生成的PDF文件。cStringIO提供了一个用C编写的类似文件对象的接口,从而可以使系统的效率最高。
下面是使用cStringIO重写的HelloWorld例子:
fromcStringIOimportStringIO fromreportlab.pdfgenimportcanvas fromdjango.httpimportHttpResponse defhello_pdf(request): #CreatetheHttpResponseobjectwiththeappropriatePDFheaders. response=HttpResponse(mimetype='application/pdf') response['Content-Disposition']='attachment;filename=hello.pdf' temp=StringIO() #CreatethePDFobject,usingtheStringIOobjectasits"file." p=canvas.Canvas(temp) #DrawthingsonthePDF.Here'swherethePDFgenerationhappens. #SeetheReportLabdocumentationforthefulllistoffunctionality. p.drawString(100,100,"Helloworld.") #ClosethePDFobjectcleanly. p.showPage() p.save() #GetthevalueoftheStringIObufferandwriteittotheresponse. response.write(temp.getvalue()) returnresponse
其它的可能性
使用Python可以生成许多其它类型的内容,下面介绍的是一些其它的想法和一些可以用以实现它们的库。Hereareafewmoreideasandsomepointerstolibrariesyoucouldusetoimplementthem:
ZIP文件:Python标准库中包含有zipfile模块,它可以读和写压缩的ZIP文件。它可以用于按需生成一些文件的压缩包,或者在需要时压缩大的文档。如果是TAR文件则可以使用标准库tarfile模块。
动态图片:Python图片处理库(PIL;http://www.pythonware.com/products/pil/)是极好的生成图片(PNG,JPEG,GIF以及其它许多格式)的工具。它可以用于自动为图片生成缩略图,将多张图片压缩到单独的框架中,或者是做基于Web的图片处理。
图表:Python有许多出色并且强大的图表库用以绘制图表,按需地图,表格等。我们不可能将它们全部列出,所以下面列出的是个中的翘楚。
matplotlib(http://matplotlib.sourceforge.net/)可以用于生成通常是由matlab或者Mathematica生成的高质量图表。
pygraphviz(https://networkx.lanl.gov/wiki/pygraphviz)是一个Graphviz图形布局的工具(http://graphviz.org/)的Python接口,可以用于生成结构化的图表和网络。
总之,所有可以写文件的库都可以与Django同时使用。Thepossibilitiesareimmense.
我们已经了解了生成“非HTML”内容的基本知识,让我们进一步总结一下。Django拥有很多用以生成各类“非HTML”内容的内置工具。