Flaskを使ったBMI計算アプリの作成
この記事では、Flaskを使う入門としてFlask×GoogleColaboratoryでBMI(Body Mass Index)計算アプリを作成する方法を紹介します。
BMIは身長と体重から健康状態を評価するための指標です。
単純なアプリの基礎を知るのにちょうどいいお題なので、今回はBMI計算機を作っていきます。
Python初心者でも理解しやすいように、コードを分かりやすく説明します。
必要なライブラリのインポート
まず、Flaskアプリケーションを作成するために必要なライブラリをインポートします。
from flask import Flask, request, render_template
Flask
: Flaskウェブアプリケーションの基本的な機能を提供するライブラリです。request
: クライアントからのHTTPリクエストデータを操作するためのモジュールです。render_template
: HTMLテンプレートをレンダリングするための関数です。
Flaskアプリケーションの初期化
次に、Flaskアプリケーションを初期化します。
app = Flask(__name__)
Flask(__name__)
は、アプリケーションを初期化し、app
変数にFlaskインスタンスを格納します。
BMI計算ロジックの追加
BMIを計算するための関数を追加します。
def calculate_bmi(height_cm, weight_kg):
try:
height_m = height_cm / 100
bmi = weight_kg / (height_m * height_m)
return bmi
except ZeroDivisionError:
return None
この関数は、身長(センチメートル)と体重(キログラム)を受け取り、BMIを計算します。計算中にゼロ除算エラーが発生した場合はNone
を返します。
ルートエンドポイントの設定
次に、ルートエンドポイントを設定します。
@app.route("/", methods=["GET", "POST"])
このコードは、”/”(ルートパス)にアクセスがあった場合に、GETとPOSTの両方のHTTPメソッドを受け付けるエンドポイントを定義しています。これにより、BMI計算フォームを表示し、計算を行うことができます。
BMI計算エンドポイントの実装
BMI計算エンドポイントは、BMI計算フォームからのPOSTリクエストを処理し、BMIを計算して結果を表示します。
@app.route("/", methods=["GET", "POST"])
def calculate_bmi_endpoint():
if request.method == "POST":
try:
# フォームから送信された身長と体重のデータを取得
height = float(request.form["height"])
weight = float(request.form["weight"])
# BMIを計算
bmi = calculate_bmi(height, weight)
if bmi is not None:
# BMIが正常に計算された場合
result = f"Your BMI is {bmi:.2f}"
else:
# 計算エラー: 身長が0の場合
result = "Height cannot be zero."
except ValueError:
# 入力が無効な場合
result = "Invalid input. Please enter valid height and weight."
# 計算結果をHTMLテンプレートに渡し、結果ページを表示
return render_template("bmi_result.html", result=result)
# GETリクエストが送信された場合はBMI計算フォームを表示
return render_template("bmi.html")
このコードの詳細は以下の通りです:
-
@app.route("/", methods=["GET", "POST"])
: このデコレータは、ルートパス (“/”) に対するGETとPOSTの両方のHTTPメソッドを処理するためのエンドポイントを定義します。 -
if request.method == "POST":
: リクエストがPOSTメソッドであるかどうかを確認します。POSTリクエストはフォームデータを送信するために使用されます。 -
height = float(request.form["height"])
およびweight = float(request.form["weight"])
: POSTリクエストからフォームで送信された身長と体重のデータを取得し、それぞれheight
とweight
変数に格納します。 -
bmi = calculate_bmi(height, weight)
:calculate_bmi
関数を呼び出してBMIを計算し、結果をbmi
変数に格納します。 -
if bmi is not None:
: BMIが正常に計算された場合をチェックします。BMIがNone
でない場合、計算結果をresult
変数に格納します。 -
else:
: BMI計算中にエラーが発生した場合、例えば身長が0の場合、エラーメッセージをresult
変数に格納します。 -
return render_template("bmi_result.html", result=result)
: 計算結果をHTMLテンプレートに渡し、結果ページ (“bmi_result.html”) を表示します。結果はBMIが計算されたか、エラーメッセージが表示されます。 -
最後の
return
ステートメントは、GETリクエストが送信された場合にBMI計算フォームを表示するためのものです。
このコードを通じて、BMI計算エンドポイントがPOSTリクエストを受け取り、身長と体重を取得し、BMIを計算して結果を表示する仕組みが理解できると思います。
次に、BMI計算フォームと計算結果を表示するHTMLテンプレートについて説明します。
BMI計算フォームのHTML
bmi.html
BMI計算フォームを含むbmi.html
のコードについて、詳しく説明します。
以下がbmi.html
のHTMLコードです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BMI Calculator</title>
</head>
<body>
<h1>BMI Calculator</h1>
<form method="post">
<label for="height">Height (cm):</label>
<input type="number" name="height" id="height" required>
<br>
<label for="weight">Weight (kg):</label>
<input type="number" name="weight" id="weight" required>
<br>
<input type="submit" value="Calculate BMI">
</form>
</body>
</html>
-
<!doctype html>
: HTML文書のDOCTYPE宣言です。HTML5文書であることを示します。 -
<html lang="en">
: HTML文書のルート要素で、言語属性が設定されています。 -
<head>
セクション: ページのメタ情報やタイトルなどのヘッダー情報を含むセクションです。 -
<meta charset="utf-8">
: 文字エンコーディングがUTF-8であることを示します。 -
<title>BMI Calculator</title>
: ページのタイトルを設定します。 -
<body>
セクション: ページの本文を含むセクションです。 -
<h1>BMI Calculator</h1>
: ページの見出しとして”BMI Calculator”を表示します。 -
<form method="post">
: BMI計算フォームを表示するためのフォーム要素です。method="post"
属性により、フォームデータがPOSTリクエストとして送信されます。-
<label for="height">Height (cm):</label>
: 身長の入力フィールドのラベルです。for
属性はラベルと入力フィールドを関連付けます。 -
<input type="number" name="height" id="height" required>
: 身長を入力するための数値入力フィールドです。name
属性はフォームデータのキーを指定し、id
属性はラベルと関連付けられます。required
属性により、このフィールドは必須入力です。 -
同様に、体重を入力するためのラベルと数値入力フィールドが続きます。
-
-
<input type="submit" value="Calculate BMI">
: BMIを計算するためのボタンです。ユーザーがこのボタンをクリックすると、フォームデータが送信されます。
このbmi.html
ファイルはBMI計算フォームを含み、ユーザーが身長と体重を入力してBMIを計算できるようになっています。フォームが送信された場合、app.py
のBMI計算エンドポイントがこれらの値を取得し、BMIを計算します。
bmi_result.html
のHTMLコードについて詳しく説明します。
bmi_result.html
以下がbmi_result.html
のHTMLコードです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BMI Calculator Result</title>
</head>
<body>
<h1>BMI Calculator Result</h1>
<div id="result">
{% if result %}
<p>{{ result }}</p>
{% endif %}
</div>
<br>
<a href="/">Back to BMI Calculator</a>
</body>
</html>
-
<body>
セクション -
<h1>BMI Calculator Result</h1>
: ページの見出しとして”BMI Calculator Result”を表示します。 -
<div id="result">
: BMI計算結果を表示するためのresult
というIDを持つ<div>
要素です。この要素内にBMI計算結果が表示されます。-
{% if result %}
: テンプレートエンジンで条件文を開始します。この部分はPythonコードの結果に依存します。 -
<p>{{ result }}</p>
: BMI計算結果が表示される<p>
(段落)要素です。{{ result }}
はPythonコードから渡された計算結果を表示します。
-
-
<br>
: 空白行を追加します。 -
<a href="/">Back to BMI Calculator</a>
: BMI計算フォームに戻るためのリンクです。href
属性がルートパス (“/”) にリンクしています。
bmi_result.html
ファイルは、BMI計算結果を表示するためのページです。BMI計算フォームから送信されたデータがBMI計算エンドポイントで計算され、その結果がこのページに表示されます。また、BMI計算フォームに戻るリンクも提供されています。
アプリをGoogleColabで起動する
!pip install flask
ライブラリを入れます。
#@title Flask
project_name = "bmi_app"
#@title サーバー
port = "8000"
host = True
from google.colab.output import eval_js
host = eval_js(f"google.colab.kernel.proxyPort({str(port)})")
サーバー関連の設定をします。
!rm -rf $project_name
!mkdir $project_name && mkdir $project_name/templates && mkdir $project_name/static
プロジェクトを作成します。
各ファイルのコードを生成していきます。
%%writefile $project_name/app.py
from flask import Flask, request, render_template
app = Flask(__name__)
# BMI計算ロジックを追加
def calculate_bmi(height_cm, weight_kg):
try:
height_m = height_cm / 100
bmi = weight_kg / (height_m * height_m)
return bmi
except ZeroDivisionError:
return None
@app.route("/", methods=["GET", "POST"])
def calculate_bmi_endpoint():
if request.method == "POST":
try:
height = float(request.form["height"])
weight = float(request.form["weight"])
bmi = calculate_bmi(height, weight)
if bmi is not None:
result = f"Your BMI is {bmi:.2f}"
else:
result = "Height cannot be zero."
except ValueError:
result = "Invalid input. Please enter valid height and weight."
return render_template("bmi_result.html", result=result)
return render_template("bmi.html")
if __name__ == "__main__":
import sys
args = sys.argv
app.run(debug=True, port=args[1])
%%writefile $project_name/templates/bmi.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BMI Calculator</title>
</head>
<body>
<h1>BMI Calculator</h1>
<form method="post">
<label for="height">Height (cm):</label>
<input type="number" name="height" id="height" required>
<br>
<label for="weight">Weight (kg):</label>
<input type="number" name="weight" id="weight" required>
<br>
<input type="submit" value="Calculate BMI">
</form>
</body>
</html>
%%writefile $project_name/templates/bmi_result.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>BMI Calculator Result</title>
</head>
<body>
<h1>BMI Calculator Result</h1>
<div id="result">
{% if result %}
<p>{{ result }}</p>
{% endif %}
</div>
<br>
<a href="/">Back to BMI Calculator</a>
</body>
</html>
print('1つ下のコードが起動してから、↓のurlにアクセスする(ただし、下のコードを実行する前に実行してください)')
print(host)
アクセスするURLを表示します。
!python $project_name/app.py $port
アプリを実行します。
実行後に一つ前で表示したURLをクリックしてアプリにアクセスします。