Flask-wtfでvalidatorsの追加
この記事はFlask-wtf (WTForms)で既存のvalidatorの追加から自作のvalidatorを作成してユ一ザ一名の重複を検知する流れについてのメモです。
対象とする読者
以下の記事を読んだことのある方やドキュメントを眺めたりして大体の使い方を知っている方
validatorの追加
WTForm(ここではflaskの拡張を使っている)のvalidationにはvalidators
を指定してvalidationを追加することができる。以下のSigupForm
はvalidationが何も無い例。
from flask_wtf import FlaskForm from wtforms import TextField, TextAreaField class SignupForm(FlaskForm): name = TextAreaField("ユ一ザー名", validators=[]) email = TextAreaField("メ一ルアドレス", validators=[])
以下はそれらしいチェックを加えたもの。
Required
, Length
, regex
を使っている。それぞれのチェックが失敗するとmessage
がfieldのerrorsに追加されていく。
from flask_wtf import FlaskForm from wtforms import Form, TextField, TextAreaField, FileField, PasswordField from wtforms.validators import Required, Length, regexp class SignupForm(FlaskForm): name = TextAreaField("ユ一ザー名", validators=[ Required("回答を入力してください"), Length(min=3, max=30, message="ユ一ザ一名は3文字以上30文字以内にしてください") ]) email = TextAreaField("メ一ルアドレス", validators=[ Required("回答を入力してください"), Length(min=1, max=50, message="メ一ルアドレスは50文字以内にしてください"), regexp( '^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$', message="無効なメ一ルアドレスです" ), ])
自分でvalidatorを作る場合はformとfieldをそれぞれ受け取る関数を与えてやれば良い。たとえば上記のフォ一ムのname
がDB上で一意な値であってほしい時はそれを判定する関数を作り、validatorsの要素にする。
以下がその例で、User.exists_by_name
は名前の通り、name
でユ一ザ一が存在するかをTrue
かFalse
で返す関数。
def unique_user(form, user): if User.exists_by_name(user.data): user.errors += ['入力したユ一ザ一名は既に使用されています'] return False return True class SignupForm(FlaskForm): name = TextAreaField("ユ一ザー名", validators=[ # 省略, unique_user ]) email = TextAreaField("メ一ルアドレス", validators=[ # 省略 ])
あとはエラ一があればそれを適当に表示させれば完了
{% for err in form.name.errors %} <span>{{err}}</span><br> {% endfor %}
ちなみにformの利用方法とかは↓みたいにnot form.validate()
で十分なはず。
ここでFalse
になれば勝手に各フィ一ルドの errors
にエラ一の内容が入ってくれる。
@app.route('/signup', methods=['GET']) def signup_get(): form = SignupForm(request.form) return render_template('signup.html', form=form) @app.route('/signup', methods=['POST']) def signup(): form = SignupForm(request.form) if not form.validate(): return render_template('signup.html', form=form) # ...