Django PDF 出力
1. 日本語対応フォントの印トール
日本語対応フォントを、staticディレクトリにインストールする
2. xhtml2pdf のインストール
pip install xmhtl2pdf
3.Viewの作成
Renderクラスを作成。このクラスをHTMLで作成されたデータを
xhml2pdfのpisaDocuemtクラスを使用しPDFへ変換する
処理を行うクラス。render
メソッドが処理で、リンク先のファイルを
読み込みをlink_callback
関数で定義している。
class Render:
@staticmethod
def render(path: str, params: dict):
template = get_template(path)
html = template.render(params)
response = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")),
response,
encoding='utf-8',
link_callback=Render.link_callback)
if not pdf.err:
return HttpResponse(response.getvalue(), content_type='application/pdf')
else:
return HttpResponse("Error Rendering PDF", status=400)
@staticmethod
def link_callback(uri, rel):
sUrl = settings.STATIC_URL
sRoot = settings.STATIC_ROOT
path = os.path.join(sRoot, uri.replace(sUrl, ""))
if not os.path.isfile(path):
raise Exception(
'%s must start with %s' % \
(uri, sUrl)
)
return path
注意
settings.pyはSTATIC_ROOTを追加しておく
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
python manage.py collectstatic
実行しておく
4 View関数の作成
戻り値にRenderクラスのrenderを呼び出すように作成する
class Pdf(View):
def get(self, request):
orders = Order.objects.all()
today = timezone.now()
params = {
'today': today,
'orders': orders,
'request': request
}
return Render.render('pdf.html', params)
_
URLの指定
urlpatterns = [
・・・
path('render/pdf/', Pdf.as_view()),
5.テンプレートの作成
テンプレートファイルに日本語のフォントを指定し、作成する。
<!doctype html>
{% load static %}
<html>
<head>
<meta charset="utf-8">
<title>Sales Report</title>
<style type="text/css">
@font-face {
font-family: "japanese";
src: url("{% static 'ipam.ttf' %}");
}
@page {
size: A4;
margin: 1cm;
font-family: "japanese";
}
html, body {
font-family: "japanese";
}
.table {
width: 100%;
max-width: 100%;
margin-bottom: 5px;
background-color: #fff;
}
.table th,
.table td {
padding: 5px;
vertical-align: top;
border-top: 1px solid #000;
text-align: center;
}
.table thead th {
vertical-align: bottom;
border-bottom: 2px solid #000;
}
.table tbody + tbody {
border-top: 2px solid #000;
}
.table .table {
background-color: #fff;
}
.list-group {
display: block;
width: 100%;
list-style: none;
margin-top: 15px;
margin-bottom: 15px;
}
.list-group p {
width: 100%;
height: 20px;
line-height: 20px;
list-style: none;
font-size: 1.1em;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="card-header">
<h3>Sales Report - {{ today | date:"d/m/Y" }}</h3>
</div>
<div class="list-group">
<p>Name: {{ request.user.first_name }} {{ request.user.last_name }}</p>
</div>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Customer</th>
<th>Subject</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{% for order in orders %}
<tr>
<td>{{ order.created_at | date:"Y/m/d" }}</td>
<td>{{ order.customer.name }}</td>
<td>{{ order.subhect }}</td>
<td>¥{{ order.price }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</body>
</html>