質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

19413閲覧

PythonのFlaskでのrender_templateで画像ファイルの表示方法

Gyutan

総合スコア7

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

1グッド

1クリップ

投稿2017/08/22 13:54

編集2017/08/25 14:16

###前提・実現したいこと
PythonのFlaskのフレームワークを用いて、QRコードを作成して、それを表示させるプログラムを作成しています。(python3)
わからないこと
QRコードをio.BytesIO()に保存したのち、
(1)render_template()を使ってこの画像をHTMLに当てはめる方法
(2)HTML側のテンプレートの記載方法

###発生している問題・エラーメッセージ

HTMLに画像が表示されません。404エラーが出ます。

###該当のソースコード

Python

1# import module 2from flask import Flask, render_template, Response,request,redirect,url_for 3import datetime 4from PIL import Image 5import qrcode as qr 6import io 7 8# flask incetance 9app = Flask(__name__) 10 11# index page, input code 12@app.route('/') 13def index(): 14 now = datetime.datetime.now() 15 timeString = now.strftime("%Y-%m-%d %H:%M") 16 return render_template('index.html',time=timeString) 17 18 19@app.route('/input_code', methods=['POST']) 20def input_code(): 21 code_input = request.form['code'] 22 qr_img = QRmaker(code_input) 23 img_bin = io.BytesIO() 24 qr_img.save(img_bin, 'png') 25#seek(0)が必要 26 img_bin.seek(0) 27# Responseやsend_fileだとうまく表示されます。 28 return Response(img_bin, mimetype='image/png') 29 #return send_file(img_bin, mimetype='image/png') 30 31#ここの記述の仕方がわかりません。404エラーが出ます。 32 #fig_url=img_bin 33 #return render_template("output_code.html", data=code_input,fig=fig_url) 34 35# retry and quit 36@app.route('/event', methods=['POST'] ) 37def event(): 38 if request.method == 'POST': 39 if request.form['submit'] == 'Retry': 40 return redirect(url_for('index')) 41 elif request.form['submit'] == 'Quit': 42 return Response('Please close the web browser') 43 else: 44 pass # unknown 45 elif request.method == 'GET': 46 return redirect(url_for('index')) 47 48def QRmaker(code): 49 qr_img = qr.make(str(code)) #codeの文字をQRコードに変換 50 # img.show() #生成したQRコードを表示 51 ts = datetime.datetime.now() # grab the current timestamp 52 # construct filename 53 filename = "qrcode_image/{}.png".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) 54 qr_img.save(filename,"png") #QRコードに名前をつけて保存 55 56# メニュー画面作成 57if __name__ == '__main__': 58 app.run(host='0.0.0.0', debug=True)

HTML

1<!--index.html --> 2<head> 3 <title>QR Generater</title> 4</head> 5<body> 6 <p>The date and time on the server: {{ time }}</p> 7 <form action="{{ url_for('input_code') }}" method="post"> 8 <input type="text" name="code"> 9 <input type="submit"> 10 </form> 11</body> 12</html>

HTML

1<!--output_code.html --> 2<head> 3 <meta charset="UTF-8"> 4 <title>QR Code</title> 5</head> 6 <body> 7 <form action={{ url_for('event') }} method="post"> 8 <input type="submit" name="submit" value="Retry"> 9 <input type="submit" name="submit" value="Quit"> 10 <br> 11 <h2>{{data}}</h2> 12 13 <h2>QR image</h2> 14<!--ここの記述があっているかどうかわかりません。--> 15 <img src="{{fig }}"> 16 </body> 17</html>

###補足情報

toda_tech👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

画像ファイルを静的に保存しないで、render_template()を使って表示する方法

このようにしてみました。(動作確認済、未テスト)

HTMLのimage要素にはsrc属性にbase64でエンコードしたメディア情報を埋め込むことでも画像が表示できるので、
今回はそれを利用しました。画像名はalt属性に挿入しました。

# coding:utf-8 # ---app.py--- from flask import Flask, render_template, Response,request,redirect,url_for import datetime from PIL import Image import qrcode as qr import base64 from io import BytesIO # flask incetance app = Flask(__name__) # index page, input code @app.route('/') def index(): now = datetime.datetime.now() timeString = now.strftime("%Y-%m-%d %H:%M") return render_template('index.html',time=timeString) @app.route('/input_code', methods=['POST']) def input_code(): code_input = request.form['code'] qr_b64data = qrmaker(str(code_input)) ts = datetime.datetime.now() qr_name = "qrcode_image_{}".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) return render_template("output_code.html", data=code_input, qr_b64data=qr_b64data, qr_name=qr_name ) # retry and quit @app.route('/event', methods=['POST'] ) def event(): if request.method == 'POST': if request.form['submit'] == 'Retry': return redirect(url_for('index')) elif request.form['submit'] == 'Quit': return Response('Please close the web browser') else: pass # unknown elif request.method == 'GET': return redirect(url_for('index')) # QRmakerという名前はpythonの命名規則に反するように思われるのですべて小文字にしました。 def qrmaker(code): qr_img = qr.make(str(code)) # 画像書き込み用バッファを確保して画像データをそこに書き込む buf = BytesIO() qr_img.save(buf,format="png") # バイナリデータをbase64でエンコードし、それをさらにutf-8でデコードしておく qr_b64str = base64.b64encode(buf.getvalue()).decode("utf-8") # image要素のsrc属性に埋め込めこむために、適切に付帯情報を付与する qr_b64data = "data:image/png;base64,{}".format(qr_b64str) return qr_b64data # メニュー画面作成 if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
<!--output_code.html --> <head> <meta charset="UTF-8"> <title>QR Code</title> </head> <body> <form action={{ url_for('event') }} method="post"> <input type="submit" name="submit" value="Retry"> <input type="submit" name="submit" value="Quit"> <br> <h2>{{data}}</h2> <h2>QR image</h2> <img src="{{qr_b64data}}" alt="{{qr_name}}" > </body> </html>

投稿2017/08/26 15:51

編集2017/08/26 16:20
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gyutan

2017/08/26 23:58

丁寧に大変わかりやすく解説を入れていただいたコードをご教授いただきありがとうございました。 こちらでも、動作することを確認いたしました。 Tkatayama様のご教授で勉強になったことをまとめてみました。他の方々にも大変参考になるものではないかと思いました。 (1)Flaskでデフォルトパス staticフォルダを静的ファイル置き場と認識 templatesフォルダをテンプレート置き場として認識 (なお変更も可能) (参考:http://www.yoheim.net/blog.php?q=20160505) (2)画像のメモリへの一時保存とHTMLの記載方法 ・ioモジュールの io.BytesIO()を使う ・バイナリデータをbase64にエンコードする ・HTML側のsrcの記述に合わせる HTMLの記述の中にdataというURLスキームがある。 記述形式は、「data:[<mediatype>][;base64],<data>」 例(ご回答いただいた例):「data:image/png;base64,以下データ」 (参考:https://www.softel.co.jp/blogs/tech/archives/2117) ---------ご教授いただいた例---------- # 画像書き込み用バッファを確保して画像データをそこに書き込む buf = BytesIO() qr_img.save(buf,format="png") # バイナリデータをbase64でエンコードし、それをさらにutf-8でデコードしておく qr_b64str = base64.b64encode(buf.getvalue()).decode("utf-8") # image要素のsrc属性に埋め込めこむために、適切に付帯情報を付与する qr_b64data = "data:image/png;base64,{}".format(qr_b64str) ------------------------------------------ ありがとうございました。
guest

0

該当のソースコード中のQRmaker()という関数は値を返していないのに、
input_code()中で

qr_img = QRmaker(code_input)

と記述されているのには違和感があります。

また

qr_img.save(filename,"png") #QRコードに名前をつけて保存

についてですが、これは

qr_img.save(filename) #QRコードに名前をつけて保存

と書くのが正しいのではないでしょうか?

また、特に設定しない限り、画像ファイル等の静的なリソースファイルはstaticディレクトリ以下におかないと
ルーティングできませんので、QRコード画像の生成先は

# これはNG filename = "qrcode_image/{}.png".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) # こうすべき filename = "./static/qrcode_image/{}.png".format(ts.strftime("%Y-%m-%d_%H-%M-%S"))

と書くべきです。

以上の点を考慮して、提示されたソースを以下のように修正してみました。
実行したところ、私の環境(Debian 9, Python3.6.1-64bit)では表示されました。
ちなみに、ディレクトリ構造は

├── app.py ├── static │   └── qrcode_image │   └── 2017-08-26_20-26-42.png └── templates ├── index.html └── output_code.html

のようになっています。

app.py

1 2# coding:utf-8 3 4 5from flask import Flask, render_template, Response,request,redirect,url_for 6import datetime 7from PIL import Image 8import qrcode as qr 9import io 10 11# flask incetance 12app = Flask(__name__) 13 14# index page, input code 15@app.route('/') 16def index(): 17 now = datetime.datetime.now() 18 timeString = now.strftime("%Y-%m-%d %H:%M") 19 return render_template('index.html',time=timeString) 20 21 22@app.route('/input_code', methods=['POST']) 23def input_code(): 24 code_input = request.form['code'] 25 fig_url = QRmaker(code_input) 26 return render_template("output_code.html", data=code_input,fig=fig_url) 27 28# retry and quit 29@app.route('/event', methods=['POST'] ) 30def event(): 31 if request.method == 'POST': 32 if request.form['submit'] == 'Retry': 33 return redirect(url_for('index')) 34 elif request.form['submit'] == 'Quit': 35 return Response('Please close the web browser') 36 else: 37 pass # unknown 38 elif request.method == 'GET': 39 return redirect(url_for('index')) 40 41def QRmaker(code): 42 qr_img = qr.make(str(code)) #codeの文字をQRコードに変換 43 # img.show() #生成したQRコードを表示 44 ts = datetime.datetime.now() # grab the current timestamp 45 # construct filename 46 filename = "./static/qrcode_image/{}.png".format(ts.strftime("%Y-%m-%d_%H-%M-%S")) 47 qr_img.save(filename) #QRコードに名前をつけて保存 48 return filename 49 50# メニュー画面作成 51if __name__ == '__main__': 52 app.run(host='0.0.0.0', debug=True) 53

投稿2017/08/26 11:40

編集2017/08/26 11:43
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gyutan

2017/08/26 14:57

コードをよく見ていただき、修正してくださりありがとうございました。 ご指摘の通りにコードを修正したところ、QRコードイメージをテンプレート内に当てはめて表示することができました。 また、ご質問の箇所ですが、(qr_img.save(filename)) すでに、filenameに拡張子が入っておりますので、ご指摘の通り改めて書く必要はないと思います。 さらに、コメントいただいた「画像ファイル等の静的なリソースファイルはstaticディレクトリ以下におかないとルーティングできません」という基礎的なことを知らなかったので大変参考になりました。 もしご存知でしたら、画像ファイルを静的に保存しないで(メモリー上にのみ保存、io.BytesIO()利用)、render_template()を使って表示する方法を教えていただけるとありがたいです。 Responseやsend_fileの方法の例はいくつかWebサイトに載っているのですが、テンプレートに当てはめる方法がなかなか見つけられないでいます。
退会済みユーザー

退会済みユーザー

2017/08/26 16:01 編集

> 画像ファイル等の静的なリソースファイルはstaticディレクトリ以下におかないとルーティングできません その点については、http://www.yoheim.net/blog.php?q=20160505 にかかれてある記事が、 staticディレクトリの他、templatesディレクトリのことなども書いてあるので、参考になると思います。 また画像ファイルを静的に保存しないで、render_template()を使って表示する方法については、改めて回答させていただきましたのでご確認下さい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問