鍍金池/ 教程/ Python/ 使用Django輸出PDF
點(diǎn)擊劫持保護(hù)
安全問題歸檔
Model 類參考
將遺留數(shù)據(jù)庫(kù)整合到Django
關(guān)聯(lián)對(duì)象參考
內(nèi)建基于類的視圖的API
聚合
Django 中的用戶認(rèn)證
django.contrib.humanize
Django管理文檔生成器
分頁(yè)
使用Django輸出CSV
加密簽名
文件儲(chǔ)存API
安全
Django中的測(cè)試
國(guó)際化和本地化
為Django編寫首個(gè)補(bǔ)丁
條件表達(dá)式
日志
模型元選項(xiàng)
部署靜態(tài)文件
執(zhí)行查詢
使用Django認(rèn)證系統(tǒng)
基于類的視圖
中間件
編寫自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫(kù)訪問優(yōu)化
錯(cuò)誤報(bào)告
基于類的內(nèi)建通用視圖
編寫自定義存儲(chǔ)系統(tǒng)
編寫你的第一個(gè) Django 程序 第3部分
編寫數(shù)據(jù)庫(kù)遷移
使用表單
編寫你的第一個(gè) Django 程序 第2部分
編寫你的第一個(gè) Django 程序 第1部分
如何使用會(huì)話
系統(tǒng)檢查框架
新手入門
信號(hào)
編寫視圖
如何使用WSGI 部署
編寫你的第一個(gè)Django應(yīng)用,第6部分
常見的網(wǎng)站應(yīng)用工具
Widgets
內(nèi)建的視圖
模型實(shí)例參考
視圖層
Django中的密碼管理
高級(jí)教程:如何編寫可重用的應(yīng)用
國(guó)際化和本地化
"本地特色"附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類)
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫(kù)函數(shù)
自定義查找
使用基于類的視圖處理表單
管理操作
開發(fā)過程
編寫你的第一個(gè)Django應(yīng)用,第5部分
進(jìn)行原始的sql查詢
模型層
多數(shù)據(jù)庫(kù)
編寫你的第一個(gè) Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應(yīng)用
按需內(nèi)容處理
管理器
視圖裝飾器
驗(yàn)證器
使用Django輸出PDF
File對(duì)象
Django 的快捷函數(shù)
基于類的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

使用Django輸出PDF

這篇文檔闡述了如何通過使用Django視圖動(dòng)態(tài)輸出PDF。這可以通過一個(gè)出色的、開源的Python PDF庫(kù)ReportLab來(lái)實(shí)現(xiàn)。

動(dòng)態(tài)生成PDF文件的優(yōu)點(diǎn)是,你可以為不同目的創(chuàng)建自定義的PDF -- 這就是說,為不同的用戶或者不同的內(nèi)容。

例如,Django在kusports.com上用來(lái)為那些參加March Madness比賽的人,生成自定義的,便于打印的 NCAA 錦標(biāo)賽晉級(jí)表作為PDF文件。

安裝ReportLab

ReportLab庫(kù)在PyPI上提供。也可以下載到用戶指南 (PDF文件,不是巧合)。 你可以使用pip來(lái)安裝ReportLab:

$ pip install reportlab

通過在Python交互解釋器中導(dǎo)入它來(lái)測(cè)試你的安裝:

>>> import reportlab

若沒有拋出任何錯(cuò)誤,則已安裝成功。

編寫你的視圖

使用Django動(dòng)態(tài)生成PDF的關(guān)鍵是,ReportLab API作用于類似于文件的對(duì)象,并且Django的 HttpResponse對(duì)象就是類似于文件的對(duì)象。

這里是一個(gè) “Hello World”的例子:

from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.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

代碼和注釋是不用多說的,但是一些事情需要提醒一下:

  • 響應(yīng)對(duì)象獲得了一個(gè)特殊的MIME類型, application/pdf。這會(huì)告訴瀏覽器,文檔是個(gè)PDF文件而不是HTML文件。 如果你把它去掉,瀏覽器可能會(huì)把輸出解釋為HTML,會(huì)在瀏覽器窗口中顯示一篇丑陋的、可怕的官樣文章。
  • 響應(yīng)對(duì)象獲取了附加的Content-Disposition協(xié)議頭,它含有PDF文件的名稱。 文件名可以是任意的;你想把它叫做什么都可以。瀏覽器會(huì)在”另存為“對(duì)話框中使用它,或者其它。
  • 在這個(gè)例子中,Content-Disposition 協(xié)議頭以 'attachment;' 開頭。 這樣就強(qiáng)制讓瀏覽器彈出對(duì)話框來(lái)提示或者確認(rèn),如果機(jī)器上設(shè)置了默認(rèn)值要如何處理文檔。如果你去掉了'attachment;',無(wú)論什么程序或控件被設(shè)置為用于處理PDF,瀏覽器都會(huì)使用它。代碼就像這樣:
response['Content-Disposition'] = 'filename="somefilename.pdf"'
  • 鉤住ReportLab API 非常簡(jiǎn)單:只需要向canvas.Canvas傳遞response作為第一個(gè)參數(shù)。Canvas函數(shù)接受一個(gè)類似于文件的對(duì)象,而 HttpResponse對(duì)象正好合適。
  • 注意所有隨后的PDF生成方法都在PDF對(duì)象(這個(gè)例子是p)上調(diào)用,而不是response對(duì)象上。
  • 最后,在PDF文件上調(diào)用showPage()save()非常重要。

注意

ReportLab并不是線程安全的。一些用戶報(bào)告了一些奇怪的問題,在構(gòu)建生成PDF的Django視圖時(shí)出現(xiàn),這些視圖在同一時(shí)間被很多人訪問。

復(fù)雜的PDF

如果你使用ReportLab創(chuàng)建復(fù)雜的PDF文檔,考慮使用io庫(kù)作為你PDF文件的臨時(shí)保存地點(diǎn)。這個(gè)庫(kù)提供了一個(gè)類似于文件的對(duì)象接口,非常實(shí)用。這個(gè)是上面的“Hello World”示例采用 io重寫后的樣子:

from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'

    buffer = BytesIO()

    # Create the PDF object, using the BytesIO object 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.
    p.showPage()
    p.save()

    # Get the value of the BytesIO buffer and write it to the response.
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response

更多資源

  • PDFlib與Python捆綁的另一個(gè)PDF生成庫(kù)。在Django中使用它的方法和這篇文章所闡述的相同。
  • Pisa XHTML2PDF是另一個(gè)PDF生成庫(kù)。Pisa自帶了如何將 Pisa 集成到 Django的例子。
  • HTMLdoc是一個(gè)命令行腳本,它可以把HTML轉(zhuǎn)換為PDF。它并沒有Python接口,但是你可以使用system 或者 popen,在控制臺(tái)中使用它,然后再Python中取回輸出。

其它格式

要注意在這些例子中并沒有很多PDF特定的東西 -- 只是使用了reportlab。你可以使用相似的技巧來(lái)生成任何格式,只要你可以找到對(duì)應(yīng)的Python庫(kù)。關(guān)于用于生成基于文本的格式的其它例子和技巧,另見使用Django輸出CSV。

譯者:Django 文檔協(xié)作翻譯小組,原文:Generating PDF。

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。