【Django(コピペ可)】html を pdf に変換する

lettersPythonアプリ

本日は、Djangoにて、

htmlをpdfへ変換し、ダウンロードする

方法を公開します

現時点(2021年3月29日)で試したところ、うまく行きましたので参考になれば幸いです

また、こちらのドキュメントを参考にしてますので、英語でも問題ない!という方は一緒に読み進めることをお勧めします!

はじめに

今回は簡易的な、請求書フォームのようなものを作っています

本当に簡易的なものですので、下記を読んでやり方を覚えたらカスタマイズしてください!

【views.py】

import os
from django.conf import settings
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
from django.contrib.staticfiles import finders

import datetime

def link_callback(uri, rel):
        result = finders.find(uri)
        if result:
                if not isinstance(result, (list, tuple)):
                        result = [result]
                result = list(os.path.realpath(path) for path in result)
                path=result[0]
        else:
                sUrl = settings.STATIC_URL        
                sRoot = settings.STATIC_ROOT      
                mUrl = settings.MEDIA_URL         
                mRoot = settings.MEDIA_ROOT       

                if uri.startswith(mUrl):
                        path = os.path.join(mRoot, uri.replace(mUrl, ""))
                elif uri.startswith(sUrl):
                        path = os.path.join(sRoot, uri.replace(sUrl, ""))
                else:
                        return uri

        if not os.path.isfile(path):
                raise Exception(
                        'media URI must start with %s or %s' % (sUrl, mUrl)
                )
        return path

def render_pdf_view(request):
    template_path = 'realestate/invoice.html' #ここにはテンプレートの場所を入れる

#ここがテンプレート内にレンダーされるcontextになります
    context = {'title': 'Invoice',
               'today': datetime.date.today(), 
               'amount': 39.99,
               'customer_name': 'Yulikepython',
               'order_id': 1233434,
    }

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="report.pdf"'

    template = get_template(template_path)
    html = template.render(context)

    pisa_status = pisa.CreatePDF(
       html, dest=response, link_callback=link_callback)

    if pisa_status.err:
       return HttpResponse('We had some errors <pre>' + html + '</pre>')
    return response

基本はコピペで大丈夫かと思います

変更すべき点は主に2箇所

  1. template_path
  2. context

になります!

【テンプレート】

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Title</title>
        <style type="text/css">
            body {
                font-weight: 200;
                font-size: 14px;
                font-family: HeiseiMin-W3;
            }
            .header {
                font-size: 20px;
                font-weight: 100;
                text-align: center;
                color: #007cae;
            }
            .title {
                font-size: 22px;
                font-weight: 100;
               /* text-align: right;*/
               padding: 10px 20px 0px 20px;  
            }
            .title span {
                color: #007cae;
            }
            .details {
                padding: 10px 20px 0px 20px;
                text-align: left !important;
                /*margin-left: 40%;*/
            }
            .hrItem {
                border: none;
                height: 1px;
                /* Set the hr color */
                color: #333; /* old IE */
                background-color: #fff; /* Modern Browsers */
            }
        </style>
    </head>
    <body>
        <div class='wrapper'>
            <div class='header'>
                <p class='title'>Invoice #{{ order_id }} </p>
            </div>
        <div>
        <div class='details'>
            Title: {{title}}<br /> 
            Bill to: {{ customer_name }}<br/>
            Amount:  {{ amount }}<br/>
            Date: {{today}}
            <hr class='hrItem' />
        </div>
    </div>
    </body>
</html>

ポイントとしては、

font-familyをHeiseiMin-W3

にすることで日本語が文字化けしなくなります

また、styleを同ページで記述していること

別ファイルのcssを読み込んでもできるかどうかは試していませんので、興味のある方は試してみて下さい!

そしてできたら教えて下さい!!

【urls.py】

from .views import (
     .,
                      .,
                      render_pdf_view,
                    )

urlspattern = [
    path("generate-pdf/", render_pdf_view, name="generate_pdf"),
]

あとは、urls.pyで指定したアドレスへGO!!

当ブログでは、日報アプリ開発を通じて、Webアプリを一から開発し公開するまでを初学者の方でもわかるようにと記事を連載しています

「Djangoでのアプリ開発を学びたい!」
「Djangoで開発したアプリをWebで公開するにはどうするの?」

という方は必見です!

【Django】チュートリアル|日報アプリの開発から公開まで
Djangoのチュートリアルをお探しですか?具体的に「手を動かして作ってみたい!」という方へ向けて、誰でもできる簡易的な日報アプリの開発を通じて、Djangoの様々な機能に触れていくシリーズとなっています。PythonでWebアプリを作りたい方、必見の記事となります!
タイトルとURLをコピーしました