Pythonのflaskを使って簡単なローカルのWebアプリを作ってみる
こんにちは!
普段趣味でプログラミングをぼちぼち勉強してます。
今回はPythonのflaskを少し勉強したので、備忘録としてローカルで動く簡単なWebアプリの作り方という形でまとめてみました。
誰かの役に立ったら良いなと思います。
また、書き方が変な部分などあるかもしれませんが、何かお気付きの点がありましたら教えていただけると助かります。
flaskとは
Pythonのflask(フラスク)とは、Pythonの軽量なウェブアプリケーションフレームワークらしいです。
"軽量な"というのは、標準で提供されている機能が最小限という意味で、マイクロフレームワークと呼ぶみたいです。
Django、Bottleなど他にもPythonで使えるWebアプリケーションフレームワークがあるみたいですが、そこまで複雑なWebアプリを作るわけじゃないのならflaskを使えば大丈夫なのかな、と思っています。
という事で早速作っていこうと思います。
flaskをインストール
まずはflaskをインストールしなければ始まらないのでpipでインストールします。
pip install flask
だぁーーーっとインストールされていくと思います。
インストールが完了したら、アプリケーションを置くディレクトリ(フォルダ)を作成していきます。
簡単なWebアプリケーションと言いましたが、何を作るか言ってませんでした。
今回は簡易的な「円の面積と円周を計算するアプリ」を作ってみようと思います。
誰も得しないしょーもないアプリですけど、この記事でやりたいのは面積と円周の計算ではなくWebアプリの基本的な部分を知ることなので、基本だと思って是非一度やってみてください。
今回のWebアプリを管理する為に、どこでも良いのでフォルダを作っておいて、その中にpyファイルやhtmlファイルなどを置いていきます。
とりあえず最小限で動かしてみる
まずはメインとなる「app.py」ファイルを作成します。
とりあえずapp.pyに最小限のコードを書きます。
[app.py]
#flaskの全てをインポートする
from flask import *
#Flaskクラスをインスタンス化して変数appに割り当てる
app = Flask(__name__)
@app.route("/")
def index():
return "Hello World!!"
if __name__ == '__main__':
app.run()
app = Flask(__name__)の部分で__name__を入れるのは後から使うtemplatesディレクトリやstaticディレクトリの位置をflaskが把握する為らしいです。
その後の@app.route("/")の部分はデコレータと言って、直下に定義する関数やクラスに対して何か処理を行うモノになります。
この部分で言うと、トップページ(/)にアクセスがあった場合にindex関数を実行して処理をするという形になります。
今はHello World!!という文字列を返すだけですが、この処理の部分で表示する内容やページを操作していくような感じですね。
最後のapp.run()の部分でサーバーを起動しています。
とりあえずこれで実行してみるとコンソールに以下の文が出ると思います。
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
これでサーバーが起動されていると思うので、最後の行に書いてある「http://127.0.0.1:5000/」にブラウザでアクセスしてみましょう。
アクセスすると、真っ白な画面の左上に「Hello World!!」と表示されていると思います。
サーバーを停止させたい時は「Ctrl + C」で停止出来ます。
ちなみにこのホスト(IPアドレスの部分)を変更すると、同じネットワーク内の機器(同じWi-Fiとかで繋がれている他の機器)からでもブラウザでアクセス出来るようになります。
app.run()のところに引数を追加します。
app.run(host='PCのIPアドレス')
これで実行するとさっきコンソールに表示されていたhttp://127.0.0.1:5000/だった部分が自分のPCのIPアドレスに変わると思います。
これで同ネットワーク内からなら実行しているPC以外の機器でブラウザを使ってアクセスすると閲覧する事が出来る様になります。
計算アプリのトップページを作る
無事にHello World!!が表示されたと思うので、次はトップページにアクセスしたらHTMLのテンプレートを返して表示させるようにしていきます。
app.pyと同じ階層にtemplatesというフォルダを作成して、その中にテンプレートのhtmlを置いていきます。
まずは表示させるHTMLファイルを作成。
[index.html]
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Index Page</title>
</head>
<body>
<h1>円の面積と円周を計算してみよう</h1>
<a href='/calc'>円の面積と円周を計算してみる</a>
</body>
</html>
これでHTMLファイルができました。
HTMLではbodyというタグに囲まれた部分がブラウザで実際に表示される部分です。
あまり深くは説明しませんがbodyの中身だけ説明すると、h1という大見出しのタグとaというリンクのタグが入っています。
aというタグのhrefの部分に書いている"/calc"がリンクの移動先のURLになっています。
このaタグは基本的にGETリクエストを送信する役割をしています。
aタグをPOSTリクエストで送信する方法もあるそうです。
計算する数値を入力して送信するページを作る
そして計算する為にユーザーに直径を入力してもらわないといけないので、/calcの移動先で表示するHTMLファイルを作成します。
[calc.html]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Calculation Page</title>
</head>
<body>
<h1>面積と円周を求めたい円の直径を入力してください<h1>
<form action='/calc' method='POST'>
<input type='text' placeholder='20'>
<input type='submit' value='計算'>
</form>
</body>
</html>
h1は先程言ったように大見出しになります。
その下のformというタグはブラウザからWebアプリのサーバーに何か情報を送信する時などに使います。
その下のinputのtypeがtextのところとsubmitのところがありますが、textの方が「何か文字列を入力するフィールド」で、submitの方がサーバー側に情報を送信するボタンになります。
この例で言うと、textのフィールドに任意の直径を入力して、それをsubmitボタンでサーバーに送信するという流れになります。
これで計算する為に直径を入力して送信するHTMLファイルが出来たので、一度実行して確認してみます。
実行してhttp://127.0.0.1:5000/にアクセスしてみると以下の画像のような画面が表示されると思います
[http://127.0.0.1:5000/]
そして「円の面積を計算してみる」というリンクを押すと画面が切り替わってhttp://127.0.0.1:5000/calc/というURLに変わって以下の画像のような画面が表示されると思います。
[http://127.0.0.1:5000/calc/]
これで画面が切り替わるのが確認できました。
ここでtextのフィールドに入力してsubmitボタンを押すと計算されるようにします、今は何も処理を書いていないのでsubmitボタンを押すとMethod Not Allowedという画面に切り替わると思います。
エラー画面で「要求された URL に対してメソッドを許可されていません。」と言っています。
何も処理を書いていないので当然ですね。
ここから計算してその値を表示させるように処理を書いていきます。
計算の処理を作る
ここから円の面積と円周を計算する処理を作っていきます。
メインのプログラムと混在するとややこしくなるので、ファイルを分けるため新たに計算処理のpyファイルを作ります。
(この程度の処理なら分けなくても良いかもしれませんが、大きいプログラムを作る時とかは、分けた方が管理しやすいと思います)
app.pyと同じ階層に新たにcalculation_circle.pyを作成します。
[calculation_circle.py]
import math
def calculation_circre(diameter):
try:
diameter = int(diameter)
#半径
radius = diameter / 2
#面積
area = radius * radius * math.pi
#円周
circumference = diameter * math.pi
return area, circumference
except :
return '数値を入力してください'
if __name__ == '__main__':
input_num = input('input number : ')
print(calculation_circre(input_num))
直径を引数に入れるとその円の面積と円周を計算して結果を返してくれるだけの単純な関数を作成しました。
例外処理で、もし例外が起きた時は「数値を入力してください」という文字列が返ってくるようにしています。
今回は全部の例外をキャッチしているので細かく分けたい時はexceptを増やして例外ごとの処理を書くと良いと思います。
これをapp.pyでインポートして、使えるようにします。
計算処理をインポートしてメインのプログラムで使う
先程作成した計算処理をする為の関数をapp.pyでインポートして、http://127.0.0.1:5000/calc/から送信される直径の情報を使って計算結果を表示させてみましょう。
まずはcalculation_circle.pyの関数をインポートして、そこから処理を加えていきます。
from flask import *
#追加------------
from calculation_circle import calculation_circle
#------------------
app = Flask(__name__)
@app.route("/")
def index():
return render_template('index.html')
#変更&追加-----------------------
@app.route("/calc", methods=['GET','POST'])
def calc():
if request.method == 'GET':
return render_template('calc.html')
elif request.method == 'POST':
diameter = request.form['diameter']
result = calculation_circle(diameter)
if len(result) == 2:
return render_template('calc.html', area=result[0],circumference=result[1])
else:
return render_template('calc.html',error=result)
#-------------------------------------
if __name__ == '__main__':
app.run()
先頭で関数をインポートしています。
@app.route("/calc", methods=['GET','POST'])
このmethods=['GET','POST']の部分は、受け付けるリクエストの種類を指定するようなイメージですかね?
今回はGETリクエストとPOSTリクエストを受け付けるようにしています。
if request.method == 'GET':
ブラウザから送信されたリクエストがGETの時にcalc.htmlをレンダリングする様に処理しています。
elif request.method == 'POST':
ブラウザから送信されたリクエストがPOSTの時に計算処理をして計算結果をテンプレートに埋め込む為のデータを渡すような処理をしています。
diameter = request.form['diameter']
ここではPOSTリクエストで送信されたフォームの値を取得して変数diameterに割り当てています。
result = calculation_circle(diameter)
ここでは先程作成した関数を実行して戻り値を変数resultに割り当てています。
その後の条件分岐の部分ではresultに格納されている要素数が2だった時とそうでない時の処理を分けています。
先程作った関数の中で例外が発生した時は戻り値が1つしかないのでこのようにしています。
render_template()の第二引数以降にキーワード引数を入れる事でhtmlのテンプレートでデータを埋め込む際に使う事ができます。
次にテンプレートを変更していきます。
テンプレートを変更する
先程作成したcalc.htmlを編集して動的に結果を出力させられるようにします。
[calc.html]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>User Input and Calclation Page</title>
</head>
<body>
<h1>面積と円周を求めたい円の直径を入力してください</h1>
<form action='/calc' method='POST'>
<input name='diameter' type='text' placeholder='20'>
<input type='submit' value='計算'>
</form>
//追加--------------------
{%if area and circumference%}
<p>面積は、{{area}}</p>
<p>円周は、{{circumference}}</p>
{%else%}
<p>{{error}}</p>
{%endif%}
//--------------------------
</body>
</html>
テンプレート内で{% Pythonコード %}とするとPythonのコードを実行する事ができます。
テンプレート内で{{ 変数名 }}とするとPythonの変数を埋め込む事ができます。
まず条件分岐で変数名areaとcircumferenceが存在すれば、面積と円周を表示させるタグを埋め込んで、それぞれに変数areaとcircumferenceの値を埋め込んでいます。
そうでなければ変数名errorの値を埋め込む。
としています。
これによって動的に計算結果を変数部分に埋め込んでHTMLページを生成する事ができます。
これで一応計算のWebアプリが完成しました。
実行して計算してみるとちゃんと計算結果が表示されていると思います。
例外の文字列もちゃんと表示されています。
ただ、0を入力して送信したら何も表示されないですね(笑)また調べておこうと思います。
まとめ的なやつ
今回はPythonのflaskで簡単なWebアプリを作ってみました。
シンプルなフレームワークということもあって初心者の方でも取り組みやすいように感じました。(僕が素人なので特に…)
今回紹介したのは本当に基礎の部分だと思うので、これからもっと勉強していきたいと思います。
最後まで読んでいただきありがとうございました!
では、またお会いしましょう!