iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0

網站在需要輸出 PDF 的時候,該怎麼辦呢?Python 不是有很多函式庫嗎?這些 PDF 函式庫能不能搭配 Django 來使用呢?

有喔,django-pdfkit 就是這樣的一個套件。

django-pdfkit 使用了 pdfkit 這個函式庫來輸出 PDF,而 pdfkit 又使用了 wkhtmltopdf 來將 HTML 轉為 PDF。講到這裡,沒錯,django-pdfkit 的內部運作是這樣的,先使用 Django 的 Template engine 輸出 HTML,再使用 wkhtmltopdf 將 HTML 轉為 PDF。

安裝

首先得安裝 wkhtmltopdf,在 ubuntu 裡,使用 apt-get 就可以安裝,但是,官方建議不要用 apt-get 安裝,而是下載二進位檔案來自行安裝。django-pdfkit 的套件網頁是這樣說的,wkhtmltopdf 網站的二進位檔案有修正過的 QT 函式庫以及更好的顯示支援,所以還是自行安裝吧。

# Linux
wget http://download.gna.org/wkhtmltopdf/0.12/0.12.3/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
tar -xf wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
sudo cp -r wkhtmltox/* /usr/

# Mac / Homebrew
brew cask install wkhtmltopdf

接著,安裝套件

poetry add django-pdfkit

使用

基本的用法很簡單,繼承 PDFView ,然後指定 template_name 就可以了。

下面我們就沿用前篇文章的 treemenu 來寫一個產出 PDF 的 View:

# treemenu/views.py
from django.views.generic import TemplateView
from django_pdfkit import PDFView
from .models import MenuItem

class TreePDFView(PDFView):
    template_name = 'treemenu/treeview_pdf.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rootmenu = MenuItem.objects.filter(parent__isnull=True).first()
        context.update({
            'rootmenu': rootmenu.get_descendants(),
        })
        return context

然後在 urlpatterns 加入這個新的 View

# urls.py
from treemenu.views import TreeView, TreePDFView

# ...
urlpatterns += [
  # ...
  path('tree.pdf/', TreePDFView.as_view()),
]

以及 template

# treemenu/templates/treemenu/treeview_pdf.html
{% load mptt_tags %}
<h1>PDF Demo</h1>
<ul>
    {% recursetree rootmenu %}
        <li>
            {{ node.name }}
            {% if not node.is_leaf_node %}
                <ul class="children">
                    {{ children }}
                </ul>
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>

用 runserver 啟動以後,就可以在瀏覽器網址列裡輸入 http://localhost:8000/tree.pdf/ ,按下 Enter 後,瀏覽器會出現對話視窗,要你選擇儲存檔案的位置。選擇好儲存檔案位置後,瀏覽器就會下載 PDF 了。

如果想要直接顯示在瀏覽器視窗,可以在網址列加上參數 inline: http://localhost:8000/tree.pdf/?inline= ,這樣就會直接顯示了。

除了 inline 以外,還有其他參數可以使用:

  • download:預設是這個,下載,會出現選擇儲存檔案位置的視窗。
  • html:不輸出為 PDF,改輸出為 HTML,可以方便除錯。
  • debug:啟用 pdfkit 的除錯模式,只有 settings 裡 DEBUG=True 時才有效。

結語

靠著 pdfkit 的威力,Django 也可以輸出 PDF,這樣要製作列印用報表,就沒什麼問題了。

範例程式網址:https://github.com/elleryq/ithome-iron-2020-django/tree/day-21


上一篇
20. pytest-django
下一篇
22. django-allauth
系列文
加速你的 Django 網站開發 - Django 的好用套件30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言