#内容
Flaskでファイル送信FORMを動的に作っていて、自分なりに解を見出したのでまとめる。
関連質問は以下となる
https://teratail.com/questions/300488
https://teratail.com/questions/302044
#結論
Flaskからのレンダリングは、フォームの個数だけを指示する。
JS側でフォームの成形をする → VUEの出る幕は無し
最終的にはVue.Jsは使わないことにしました。
#解決した方法
HTMLフォームとFLASKのFORM-MODEL処理について、下記の辞書を使い紐付けを行った。
JS
dict = { "title1:"db1","title2":"db2", "title3":"db3","title4":"db4" }
python
model_table = {"db1",database1,"db2":database2,"db3":database3,"db4":database4}
全体的なループカウンタは、Flask側からJINJA2でループを回して、レンダリング時にloop.index0を使いIDタグに命名している。
DOM完成後にJSでdictのループを回して、MAPのINDEXからIDを生成し、html本文を書き換えている。
{% for i in forms %}
<h1 id = "t{{loop.index0}}"></h1>
<p>
<form id = "f{{loop.index0}}" class="form form-horizontal" method="POST" action="{{url_for('data_import')}}" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" >
</form>
</p>
{% endfor %}
<script>
var dict = { "title1:"db1","title2":"db2", "title3":"db3","title4":"db4" }
Object.keys(dict).map(function(key,index){
document.getElementById('t'+index).textContent = key;
document.getElementById('f'+index).action += "/"+dict[key];
});
</script>
Flask側はURLエンドでデータベースのモデルを特定できるようにした。
モデルを自体を直接的に辞書に突っ込んでおり、model_nameを介して
共通コードで処理している。
いったんモデルクラスに実装したdata_importというメソッドで
処理はモデル毎にカスタマイズしており、
returnされるobjectは、データのインスタンス群であり、これを一括で更新する。
model_table = {"db1",database1,"db2":database2,"db3":database3,"db4":database4}
#データインポート処理
@app.route('/import')
@app.route('/import/<model_name>',methods=["GET", "POST"])
def data_import(model_name):
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash(name + "ファイルを選択してください。", "failed")
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filename =os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filename)
model = model_table[model_name]
objects = model.data_import(filename)
db.session.bulk_save_objects(objects)
db.session.commit()
return render_template(
'table_viewer.html',
forms = range(4)
)
return render_template(
'import.html',
forms = [1,2,3,4]
)
#あとがき
何故ここまで複雑化したのかというと、いろんな理由がある。
・バックエンドの処理において、フォーム毎にバインディングしているデータベースが違うこと
・FLASK側ではORMライブラリを使い、複数ファイルに分かれたSQLITEに対して、共通化した処理でコミットさせたかった
・Flaskのテンプレート内のVIEWに関わる情報については、受け側のHTML内で処理したかった。
・POST送信はHTMLのデフォルトでやりたく、AJAX通信の複雑さをコードに入れたくなかった。
最近は便利なフレームワークが多いが、無理をせずにバニラjsで十分できることもある。
工夫されたコードはいたってシンプルであり、かつ美しいものである。