flask
from flask import Flask, render_template, request, make_response
from weasyprint import HTML
app = Flask(__name__)
@app.route('/pdf')
def create_pdf():
show_kotsuhi = request.args.get('show_kotsuhi', 'no') == 'yes'
html = render_template('report.html', show_kotsuhi=show_kotsuhi)
pdf = HTML(string=html).write_pdf()
response = make_response(pdf)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'inline;
filename=report.pdf' return response
if __name__ == '__main__': app.run()
report.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>経費レポート</title>
</head>
<body>
<h1>経費レポート</h1>
{% if show_kotsuhi %}
<h2>交通費のみ表示</h2>
<p>交通費: 10,000円</p>
{% else %}
<p>交通費は非表示です。</p>
{% endif %}
</body>
</html>
1. 交通費表示PDF → http://localhost:5000/pdf?show_kotsuhi=yes
2. 交通費非表示PDF → http://localhost:5000/pdf?show_kotsuhi=no またはパラメータなし 🔚
1. 必要ライブラリ
pip install Flask WeasyPrint
Flask
from flask import Flask, render_template, request, make_response
from weasyprint import HTML, CSS
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/generate_pdf', methods=['POST'])
def generate_pdf():
# フォームからのデータを受け取る(例: 'show_transportation' チェックボックスの値)
show_transportation = request.form.get('show_transportation') == 'on'
# HTMLテンプレートをレンダリング
rendered_html = render_template('invoice.html', show_transportation=show_transportation)
# PDFを生成
html = HTML(string=rendered_html)
pdf_bytes = html.write_pdf()
# レスポンスとしてPDFを返す
response = make_response(pdf_bytes)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'attachment; filename=invoice.pdf'
return response
if __name__ == '__main__':
app.run(debug=True)
解説:
-
@app.route('/generate_pdf', methods=['POST']):PDF生成
-
request.form.get('show_transportation') == 'on':HTMLフォームからshow_transportationのチェックボックス取得、チェック済み: True、no check : False → show_transportation変数へ。
-
render_template('invoice.html', show_transportation=show_transportation):invoice.html読み込み時
-
、show_transportation変数で条件分岐準備
-
HTML(string=rendered_html).write_pdf():レンダリングされたHTML文字列からPDF作成
-
make_response:PDFをレスポンスで返。
-
日本語フォント: *Google Fonts : Noto Sans JP → linkタグでインポート、CSSで指定
-
本番 CSSでローカルフォント指定
index.html (PDF生成のトリガフォーム)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PDF生成オプション</title>
</head>
<body>
<h1>請求書PDF生成</h1>
<form action="/generate_pdf" method="post">
<label>
<input type="checkbox" name="show_transportation" checked> 交通費を含める
</label><br><br>
<button type="submit">PDFを生成</button>
</form>
</body>
</html>
invoice.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>請求書</title>
<style>
body { font-family: 'Noto Sans JP', sans-serif; } /* 日本語フォントを指定 */
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid black; padding: 8px; text-align: left; }
</style>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<h1>請求書</h1>
<p>日付: 2025年6月25日</p>
<p>宛名: 御担当者様</p>
<table>
<thead>
<tr>
<th>項目</th>
<th>金額</th>
</tr>
</thead>
<tbody>
<tr>
<td>商品A</td>
<td>10,000円</td>
</tr>
<tr>
<td>サービスB</td>
<td>5,000円</td>
</tr>
{% if show_transportation %}
<tr>
<td>交通費</td>
<td>2,000円</td>
</tr>
{% endif %}
<tr>
<td>合計</td>
<td>
{% if show_transportation %}
{{ 10000 + 5000 + 2000 }}円
{% else %}
{{ 10000 + 5000 }}円
{% endif %}
</td>
</tr>
</tbody>
</table>
</body>
</html>
PDF生成ライブ
- ReportLab: 高機能で複雑なPDF生成むき 学習コスト 高。