
目標
- Flaskのルーティングを利用した小規模アプリを作成できる。
- フォームからサーバーに送られてきたパラメータを検証することができる。
Flaskのルーティングを利用した小規模アプリの作成
Flask-WTFライブラリの概要とインストール
Flask-WTFライブラリの概要
Flask-WTFは、FlaskとWTFormsを統合する拡張機能で、フォームの作成や管理、バリデーション、CSRF対策などの機能を提供します。
バリデーションとは、ユーザーが送信するデータが期待する形式や条件を満たしているかを確認する処理です。Flaskにはいくつかのバリデーション方法がありますが、Flask-WTF(WTForms)を使用する方法が一般的です。他にも、request.form を手動で処理する方法や、marshmallow などのライブラリを使う方法もあります。
Flask-WTFのインストールとセットアップ
Flask-WTFをインストールします。
C:\Users\user\Desktop\FlaskProj>.venv\Scripts\activate
# 仮想環境が有効化されます。
(venv) C:\Users\user\Desktop\FlaskProj>pip install flask-wtf

FlaskアプリケーションでFlask-WTFを使用するためにインポートします。(クラスの作成時にインポートします。)
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField
from wtforms.validators import DataRequired, NumberRange
Flask-WTFライブラリの利用
フォームクラスの定義
Flask-WTFを使うと、フォームはPythonのクラスとして定義されます。フォームに必要なフィールド(例えば商品名、価格など)と、そのフィールドに対するバリデーションをクラスで定義します。
以下は、商品追加フォームです。商品名には必須の入力バリデーション、価格には数値としての制限を設けています。
forms.pyファイルの作成
forms.pyファイルをminiappディレクトリに作成します。

forms.pyファイルに次のプログラムを入力します。
from flask_wtf import FlaskForm
from wtforms import IntegerField, StringField
from wtforms.validators import DataRequired, NumberRange
class AddProductForm(FlaskForm):
product_name = StringField("商品名", validators=[DataRequired()])
product_price = IntegerField(
"価格",
validators=[
DataRequired(),
NumberRange(min=1, message="価格は1以上である必要があります"),
],
)
FlaskForm:Flask-WTFのフォームクラスです。フォームを作成する際に継承します。
StringField:文字列を入力するためのフィールドです(商品名用)。
IntegerField:整数を入力するためのフィールドです(価格用)。
validators:入力値のバリデーション(検証ルール)を設定するためのクラスです。
DataRequired():値が空でないことを保証します。
NumberRange(min=1, message=”価格は1以上である必要があります”):
min=1:価格の値が1以上であることを保証します。
message:条件を満たさない場合に表示されるエラーメッセージを指定します。
Flaskビューでのフォームの利用方法
Flaskビューでのフォームの利用方法
次に、Flaskビューでフォームを利用します。フォームが正常に送信された場合に、データを処理してリダイレクトする処理を行います。
from flask import Flask, redirect, render_template, url_for
from apps.miniapp.forms import AddProductForm
app = Flask(__name__)
app.secret_key = "your_secret_key"
# 商品リスト
products = [
{"id": 1, "name": "オレンジジュース", "price": 140},
{"id": 2, "name": "アップルジュース", "price": 150},
{"id": 3, "name": "牛乳", "price": 180},
]
@app.route("/")
def index():
return "Top page"
@app.route("/products")
def product_list():
return render_template("products.html", products=products)
@app.route("/add_product", methods=["GET", "POST"])
def add_product():
form = AddProductForm()
if form.validate_on_submit():
# フォームが送信されて、かつバリデーションが成功した場合
name = form.product_name.data
price = form.product_price.data
# 新しい商品を追加
new_id = len(products) + 1
products.append({"id": new_id, "name": name, "price": price})
# 商品一覧ページにリダイレクト
return redirect(url_for("product_list"))
return render_template("add_product.html", form=form)
@app.route("/manage_products")
def manage_products():
# 商品管理ページを表示
return render_template("manage_products.html")
if __name__ == "__main__":
app.run(debug=True)
フォームの処理は次の手順で行っています。
フォームオブジェクトの作成
form = AddProductForm()でフォームオブジェクトを作成します。
フォームの送信とバリデーション
form.validate_on_submit()は、フォームがPOSTリクエストとして送信され、かつバリデーションが成功した場合にTrueを返します。これをif文の条件に設定することで、適切な場合に処理を行わせることが可能となります。
フォームデータへのアクセス
フォームのデータは、form.name.dataやform.price.dataでアクセスできます。
エラーメッセージの表示
バリデーションが失敗した場合、フォームにはエラーメッセージが表示されます。form.errorsを使って各フィールドのエラーメッセージを取得できます。
HTMLテンプレートでのフォーム表示
Flask-WTFを使ってフォームを表示する場合、Jinja2テンプレートエンジンを使って、フォームのフィールドとエラーメッセージを表示します。
add_product.htmlの商品追加フォームの内容を編集します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品追加</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<h1>商品追加ページ</h1>
<ul>
<li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧に戻る</a></li>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
</ul>
<h1>商品追加フォーム</h1>
<form method="POST" action="{{ url_for('add_product') }}">
{{ form.hidden_tag() }} <!-- CSRFトークンを含めるため -->
<label for="product_name">商品名</label>
{{ form.product_name() }} <!-- 商品名入力フィールド -->
{% if form.product_name.errors %}
<ul>
{% for error in form.product_name.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="product_price">価格</label>
{{ form.product_price() }} <!-- 価格入力フィールド -->
{% if form.product_price.errors %}
<ul>
{% for error in form.product_price.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<input type="submit" value="商品を追加する">
</form>
</body>
</html>
<form method=”POST”>の部分
<form method=”POST” action=”{{ url_for(‘add_product’) }}”> としてPOSTメソッドと送信先URLを指定しています。
{{ form.name() }}や{{ form.price() }}は、Flask-WTFで定義されたフォームフィールドを表示(利用)する部分です。form.hidden_tag()は、CSRF(クロスサイトリクエストフォージェリ)保護用の隠しタグを挿入します。フォームのバリデーションが失敗した場合は、form.name.errorsやform.price.errorsでエラーメッセージを取得し、テンプレート内で表示します。
バリデーションエラーメッセージのカスタマイズ
バリデーションエラーメッセージは、バリデータで指定することができます。例えば、NumberRange(min=1)では、価格が1未満の場合にカスタムメッセージを表示させることができます。
price = IntegerField('価格', validators=[DataRequired(), NumberRange(min=1, message="価格は1以上である必要があります")])
CSRF保護
Flask-WTFでは、デフォルトでCSRF(クロスサイトリクエストフォージェリ)保護が有効になります。これにより、フォームの送信時にCSRFトークンが必要となり、不正なリクエストを防ぐことができます。form.hidden_tag()はこのトークンをフォームに埋め込む役割を担っています。
ブラウザで http://127.0.0.1:5000/manage_productsにアクセスします。
商品管理ページが表示されます。

商品一覧ボタンを押下すると、商品一覧ページが表示されます。

商品を追加するボタンを押下すると、商品追加ページが表示されます。

商品名と価格を入力して「商品を追加する」ボタンを押下します。

http://127.0.0.1:5000/products にリダイレクトされます。

商品が追加されています。
続けて、商品追加ページで商品名を空で送信ボタンを押下します。

商品の追加はされず、商品追加ページが再表示されます。
今回は以上になります。

ブックマークのすすめ
「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

