flaskを使ったWebアプリ作成 導入と動的表示

python

 Pythonを使ったプログラムを外部から簡単に扱えるようにWebアプリにしてみたのでその覚書。別にWebアプリ開発をしたいわけではないのですが、スマホから操作したかったので。

Flaskへようこそ — Flask Documentation (2.2.x)

 が公式のドキュメントの日本語訳です。ここを端折って動かしています。一通り動かせたらこっちを参照するのが良いです。

スポンサーリンク

venvで仮想環境を作成

 まずは環境を壊さないように、最小限の仮想環境を作っておきます。ほかのライブラリが悪さをしたり、ほかのライブラリに悪さをしたり。

python -m venv [envname]

 これでひとまず素の環境を用意しときます。そのうえでactivate

[envname]\Scripts\activate

 OSによって記述は違うかもしれませんが、ひとまずこれでその仮想環境上での操作になります。

flaskをまず使う

 PythonでWebアプリを作るためのライブラリで、今回は簡単に済ませたかったのでこいつを採用しました。サーバ機能含めてコレ一つで済んでしまうので恐ろしいものです。

インストール

 インストールはいつものpipで。

pip install flask

 何事もなければ以上で終わり。あとは

from flask import Flask, request, render_template

 で動かせてしまいます。Flask以外のrequestとrender_templateの2つのライブラリはWebアクセスを受けた時の応答を解釈したり、動的にWebページを生成するために必要なものなので、ひとまず合わせてimportしときます。そのうえでまずFlaskクラスのインスタンスを作成します。

app = Flask(name, static_folder='./html/', static_url_path='/files', template_folder='./temps')

 色々ごちゃごちゃ引数つけてますがもちろんデフォルトフォルダ構成でよければ

app = Flask(__name__)

 でいいです。その起動は

app.run(host="0.0.0.0", port=80, debug=False)

 になります。ドキュメントにはコマンドからflask runを使うように記述がありますが、世の中のサンプルの大半が上記のapp.run()形式で記述があるのでこっちを採用します。どっちがどういいのか違いはよくわかりません。host引数はlocalだけでなく外部からもアクセス許可しますよぉ~の意味なので、クローズドなLAN環境であれば”0.0.0.0″で動かしてLANの中からのアクセスを許可しましょう。portは好きな値で。httpアクセスのデフォルト80番にしとくとブラウザでのアクセスが煩わしくないでしょう。攻撃受けやすくなるのかもしれませんが。

 ルートディレクトリへのアクセスイベントを捕まえるには、

@app.route('/', methods=['GET'])
def root_func_get():
    return "Hello World!"

 この記述になります。ちなみにこの@マークから始まる関数はデコレーターと呼ぶようで、app.route()関数の中でここで定義した関数が呼ばれるような構造みたいです。よくわからんけど。

 もちろん関数の名前は任意です。第一引数がアクセスを受けたアドレスで、第二引数がGETのリクエストが来たのか、POSTのリクエストが来たのか(他にもありますが…)を判別するためのmethodsになります。アクセスを受けっぱなしであればGETだけで。

 そのうえでHello Worldを返しているので、ひとまずブラウザからlocalhostにアクセスするとHello Worldが表示されます。ひとまず完成。

静的htmlファイルを表示する

 Hello Worldが出ても何もうれしくないので、あらかじめ用意したhtmlファイルを表示してみます。関数としては、Flask関数のsend_static_file(filename)を使います。これは静的なファイルを表示するためのメソッドなのでダイナミックなページの表示はできませんが、トップページくらいはこれで良いでしょう。

API — Flask Documentation (2.2.x)

 send static fileの情報は↑

 この時必要なhtmlファイルはstatic_folderに置いておく必要があります。今回flaskインスタンスを

app = Flask(__name__, static_folder='./html/', static_url_path='/files', template_folder='./temps')

 として作っているので、static_folderはこの*.pyが置いてある場所にある”html”フォルダの下になります。(デフォルトだと”static”フォルダの下)ちなみにstatic_url_pathはstaticフォルダへのアクセス時のURLになり、template_folderは後述のrender_templateを使うときのテンプレートファイルを置いておく場所です。指定せずデフォルトでもいいんですけどね。覚書なので。

@app.route('/', methods=['GET'])
def root_func_get():
    return app.send_static_file('index.html')

 これでブラウザからアクセスするとこのhtmlファイルが表示されます。

動的htmlファイルを表示する

 何も動かないhtmlファイルを表示してもWebアプリでもなんでもないので、続いて動的に変化する表示を行います。ホスト側(ブラウザ側)からPOSTしてもらった変数を受け取って、それに応じて処理をするイメージです。

 これには冒頭でimportしといたrequestで値を受け取り、render_templateモジュールを使ってhtmlを生成します。index.htmlを

<html lang="ja">
<body>
 <form method="POST">
  <label>文字列の入力<input type="text" name="text"></label>
  <input type="submit" name="confirm" value="実行"></br></br>
 </form>
</body>

</html>

 このようにして“text”というラベルがついた文字列をPOSTできるようにします。そのうえでユーザーからの入力を受け付ける必要があるのでPOSTを受ける関数を用意します。

@app.route('/', methods=['POST'])
def root_func_post():

    print("message = " + request.form.get('text'))
    return render_template('receive.html', text = request.form.get('text'))

 request.formに送られてきたデータが辞書型(厳密にはImmutableMultiDict)でやってくるのでその中身をgetメソッドで取得表示しています。そのうえで、render_templateに対してその文字列を送りつけてhtmlを生成させています。

 render_templateの引数につけたrecieve.htmlは

<!DOCTYPE html>
<html lang="ja">
<body>
 <p>送られてきた文字列は:{{text}}だね</p>
</body>

</html>

 こんな感じで用意しときます。*.pyがおいてるフォルダの直下に先に指定した名前(デフォルトだと”templates”)のフォルダを作っておいて、その中に保存しておきます。render_templateはこのフォルダにあるファイルを探して生成してくれるようです。

 受け取るメッセージの部分(今回だとtext)は2重の{ }でくくっときます。

 これで

 こんな感じで表示されたページからメッセージを送り、

 こんな感じで文字列が表示されます。

ソースコード全体

from flask import Flask, request, render_template

app = Flask(__name__, static_folder='./html/', static_url_path='/files', template_folder='./temps')

@app.route('/', methods=['GET'])
def root_func_get():
    print("GET")
    return app.send_static_file('index.html')

@app.route('/', methods=['POST'])
def root_func_post():
    print("POST")
    print("message = " + request.form.get('text'))
    return render_template('receive.html', text = request.form.get('text'))

print(app.url_map)
app.run(host="0.0.0.0", port=80, debug=False)

 色々print文をつけてますが、ひとまず最初の一歩。

python
スポンサーリンク
キャンプ工学

コメント

タイトルとURLをコピーしました