Flaskでアプリを開発している時、ある問題に直面しました。
例えばHTMLで画像を指定する場合、srcでパスとファイル名を指定する必要がありますが、アプリの仕様上このやり方ではその都度ファイル名が変更するプログラム、または毎回違うファイル名を指定することが出来ません。
じゃあどうすれば出来るのか。今回はその方法を紹介します。
・問題が発生した経緯
FlaskでCSVファイルを取得して画像を生成するアプリを作っていたのですが、画像のファイル名が毎回変わる(CSVファイル名と同じにする)ためscvで指定できなかったのです。
生成した画像をresult.pngにして、プログラムを実行するたびに内容を上書きするのを試したのですが、前の画像が生成されて断念。
他に良い方法がないか探していたら、バックエンド(Python)でパスとファイル名を変数に渡して、HTMLでその変数を指定することが出来ると知りました。
「コレだ!」と思いましたね。
コレを応用すれば、いつも名前が変わるファイル名を的確に指定することはもちろん、リスト化してランダムに指定する、なんてことも出来るでしょう。
・コードを書く(Python編)
まずはPythonで必要なコードを書きます。
Flaskの公式ページに載っているコードを基に、必要な部分を追加します。
import os from flask import Flask, request, redirect, url_for, render_template from werkzeug import secure_filename UPLOAD_FOLDER = "パス" ALLOWED_EXTENSIONS = ["csv"] app = Flask(__name__) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS @app.route('/', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(UPLOAD_FOLDER, filename)) return redirect(url_for('uploaded_file', filename=filename)) return render_template("index.html") @app.route('/uploads/<filename>') def uploaded_file(filename): os.path.abspath(UPLOAD_FOLDER + filename) return render_template("result.html")
上記のupload_file関数でファイルを受け取り、その下のuploaded_file関数でファイルを表示することが出来ます。
しかし、このままではファイル名をきっちり指定しないとプログラムが働かないので、uploaded_file関数にコードを追加します。
@app.route('/uploads/<filename>') def uploaded_file(filename): os.path.abspath(UPLOAD_FOLDER + filename) return render_template("result.html", img="パス" + filename + ".png")
returnの戻り値に注目すると、”result.html”の隣にimgの変数が追加されています。
つまり、第2引数で、パス +csvファイル名 + .png、とすることでcsvファイル名そのままを指定することが出来るのです。
でもこのままだと”~.csv.png”になるじゃん。ドットが2つ付いたらダメなんじゃないの?
大丈夫なんです(迫真)
なんかダメそうな気が(負けた気が)しますけど、動くんです(白目)
・コードを書く(HTML編)
次に実行結果を表示するrusult.htmlに簡単な変更を加えます。
公式ページにはresult.htmlが載っていませんが、画像を生成するなら基本は下記のようになるでしょう。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Result</title> </head> <body> <h2>画像が完成しました。</h2> <img src="パス/result.png" alt="result.png"> </body> </html>
コレをこのように変更します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Result</title> </head> <body> <h2>画像が完成しました。</h2> <img src={{img}} alt="result.png"> </body> </html>
imgのsrcに注目すると、通常パスとファイル名を指定する部分が {{img}} となっていることが分かります。
そうPythonで作った変数が組み込まれているのです。
やってみると、マジ単純。
まとめ
以上、いつも名前が変わるファイル名を的確に指定、実行する方法の紹介でした。
今回の方法を活用すれば、バックエンドのプログラムの都合でファイル名が変わっても、HTMLを書き換える必要がなくなります。
単純かつ応用が効く手法ですね。