目次
forms.pyとは?
forms.py
は、Flaskでフォームの管理を記述するモジュールです。
Flaskでは、フォームを手動で作成することも可能ですが、ライブラリであるWTFormsを活用することで、より簡単かつ堅牢にフォームを構築できます。
フォームの作成方法
手動でフォームを作成する
以下のコードはHTMLを直接記述してフォームを作成する方法です。
<form action="{{ url_for('app.register') }}" method="POST" enctype="multipart/form-data">
<label for="name">名前:</label>
<input type="text" id="name" name="name" placeholder="名前">
<label for="email">メールアドレス:</label>
<input type="email" id="email" name="email" placeholder="sample@sample.com">
<input type="submit" value="送信">
</form>
このように、labelを書いて、inputタグを書いて、、と面倒ですよね。。これをwtformsを使って書いてみます。
WTFormsで会員登録フォーム
forms.py
会員登録フォームをwtformsで書いてみましょう。ポイントは表示させたいフォームをクラスで書くことです。また、クラスメソッドに、バリデーションを書くことができます。
from wtforms.form import Form
from wtforms.fields import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, EqualTo, ValidationError
from flaskr.models import User
class RegisterForm(Form):
email = StringField('メール: ', validators=[DataRequired(), Email('メールアドレスが誤っています')])
username = StringField('名前: ', validators=[DataRequired()])
password = PasswordField('パスワード: ', validators=[DataRequired(), EqualTo('password_confirm', message='パスワードが一致しません')])
password_confirm = PasswordField('パスワード確認: ', validators=[DataRequired()])
submit = SubmitField('登録')
# 独自バリデーションメソッド
def validate_email(self, field):
if User.select_by_email(field.data):
raise ValidationError('メールアドレスは既に登録されています')
views.py
作成したフォームをviews.py
に書いてみます。RegisterFormはクラスで書いているのでインポートして使えます。formロジックで扱うには、form=RegisterForm()でインスタンスを作成します。さらに、入力されたデータを form.username.data のように取り出します。 ( views.py )
from .models import RegisterForm
@bp.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if request.method == 'POST' and form.validate():
user = User(
email=form.email.data,
username=form.username.data,
password=form.password.data
)
user.add_user()
return redirect(url_for('app.login'))
return render_template('register.html', form=form)
html
view関数の render_templateで、formを渡しているので、htmlで展開できます。
{% extends "base.html" %}
{% block content %}
<h1>ユーザ情報登録画面</h1>
<form method="POST">
{{ form.csrf_token }}
{{ form.email.label }}{{ form.email() }}
{{ form.username.label }}{{ form.username() }}
{{ form.password.label }}{{ form.password() }}
{{ form.password_confirm.label }}{{ form.password_confirm() }}
{{ form.submit() }}
</form>
{% endblock %}
WTFormsでログインフォーム
ログインについてもwtformsで書けます。
forms.py
class LoginForm(Form):
email = StringField('メール: ', validators=[DataRequired(), Email()])
password = PasswordField('パスワード: ', validators=[DataRequired()])
submit = SubmitField('ログイン')
views.pyでのログイン処理
@bp.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
user = User.select_by_email(form.email.data)
if user and user.validate_password(form.password.data):
login_user(user, remember=True)
next = request.args.get('next') or url_for('app.welcome')
return redirect(next)
return render_template('login.html', form=form)
html
{% from "_formhelpers.html" import render_field %}
{% extends "base.html" %}
{% block content %}
{% for message in get_flashed_messages() %} {# リダイレクトした際のメッセージ#}
{{ message }}
{% endfor %}
<form method="POST">
{{form.csrf_token}}
{{render_field(form.email)}}
{{render_field(form.password)}}
{{form.submit()}}
</form>
{% endblock %}
こちらはマクロを使った記述です。
マクロについてはこちらをご覧ください
その他の入力フォーム
会員登録、ログイン以外にも、ブラウザでformで表示するものがさまざまあります。
例えば、ラジオボタン、チェックボックス、セレクトがあります。これらをflaskで扱ってみます。
name=の部分を読み取って
view関数で
papersize = request.form[‘papersize’] のようにして、そこに入力された値を格納します。実際には、valueの値が格納されています。
セレクトボタン
form
{% extends "base.html" %}
{% block content %}
<form action="{{ url_for('select') }}" method="POST">
<label for="fruite">好きな果物</label>
<select name="selectbutton">
<option value="">選択してください</option>
<option value="banana">バナナ🍌</option>
<option value="apple">リンゴ🍎</option>
<option value="grape">ぶどう🍇</option>
<option value="orange">オレンジ🍊</option>
</select>
<input type="submit" value="送信">
</form>
メッセージ:{{ message }}
{% endblock %}
views
@app.route('/select', methods=["GET","POST"])
def select():
if request.method == "POST":
value = request.form["selectbutton"]
return render_template("selectform.html", message=value)
return render_template("selectform.html")
ラジオボタン
form
{% extends "base.html" %}
{% block content %}
<form action="{{ url_for('radio') }}" method="POST">
今日の感想<br>
<input type="radio" name="radiobutton" value="good">good<br>
<input type="radio" name="radiobutton" value="bad">bad
<br>
<input type="submit" value="送信">
</form>
メッセージ:{{ message }}
{% endblock %}
views
@app.route('/radio', methods=["GET","POST"])
def radio():
if request.method == "POST":
value = request.form["radiobutton"]
message = f"今日の感想:{value}でした"
return render_template("radioform.html", message=message)
return render_template("radioform.html")
チェックボックス
form
{% extends "base.html" %}
{% block content %}
<form action="{{ url_for('checkbox') }}" method="POST">
個人情報保護に同意した
<input type="checkbox" name="accept" value="1">
<input type="hidden" name="accept" value="0">
<input type="submit" value="送信">
</form>
{% if message %}
<p>メッセージ:{{ message }}</p>
{% endif %}
{% endblock %}
views
@app.route('/checkbox', methods=["GET","POST"])
def checkbox():
if request.method == "POST":
value = request.form.get("accept")
print(value)
if value == "1":
message = "同意しました"
else:
message = "同意してません"
return render_template("checkboxform.html", message=message)
return render_template("checkboxform.html")
まとめ
WTFormsを活用することで、Flaskでのフォーム管理が簡素化され、堅牢なアプリケーションを構築できます。ぜひこのガイドを参考に、効率的なフォーム作成を実践してみてください!
( 引用 https://tanuhack.com/flask-client2server/ )
Flaskアプリ開発の全てがここに!アプリ構成の全てはこちらをご覧ください!