LoginSignup
6
4

More than 1 year has passed since last update.

FlaskForm を利用したフォームバリデーション

Last updated at Posted at 2022-02-04

WTForm,FlaskFormを使ってみたい

FlaskFormを使うにあたり、あまり記事がなかったので備忘録もかねて記事にします。
入力フォームで送られてきたデータを受け取る動きを例にします

まず下準備

index.py
from flask import Flask
from flask_wtf import FlaskForm
from wtforms import (StringField, PasswordField, BooleanField,
                     RadioField, SelectField,SubmitField, ValidationError)

フィールドの例

StringField : 文字列
PasswordField : パスワード
BooleanField : チェックボックス
RadioField : ラジオボタン
SelectField : セレクトボックス
SubmitField : 送信ボタン
ValidationError : エラー表示

index.py
class signup_form(FlaskForm):
   """登録フォームに関するvalidate関数"""
    name = StringField(label=('名前'))

    password = PasswordField(label=('パスワード'))

    gender = RadioField(label='性別', choices=[
                        ('1', '男性'), ('2', '女性'), ('0', 'その他')])
    birth = SelectField(label=('誕生年'),
                           choices=[
                                    ('', '選択してください'),
                                    ('2021', '令和3年'),
                                    ('2022', '令和4年')
                                   ])

   shikaku1 = BooleanField(label=('基本情報技術者試験(FP)'),
                            false_values=(False, 'false', 0, '0'))
   shikaku2 = BooleanField(label=('応用情報技術者試験(AP)'),
                            false_values=(False, 'false', 0, '0'))

   submit = SubmitField(label=('登録'))
    # とりあえず使ってない、 htmlのsubumitでも動く

   def validate_name(self, name):
        """ name を検証 """
        if name.data == "":
            # if 〇〇の エラーコードを出す
            raise ValidationError('入力してください')
        if "/" in name.data:
            raise ValidationError('名前に「/」は含められません')
        if len(name.data) > 20:
            raise ValidationError('文字数が多すぎます')

    def validate_password(self, password):
        pw_pat = re.compile("^[0-9a-zA-Z]+$")
        if password.data == "":
            raise ValidationError('入力してください')

        if len(password.data) < 8 or len(password.data) > 25:
            raise ValidationError('8文字以上25文字以下')

        if not pw_pat.match(password.data):
            raise ValidationError('使用できない文字が含まれています')

    def validate_gender(self, gender):
        if gender.data is None:
            raise ValidationError('選択してください')

    def validate_birth(self, birth):
        if ken_code.data == "":
            raise ValidationError('選択してください')

フォームクラスを定義して、バリデーション内容をif文で追加していきます。
設定したバリデーションに引っかからなければ、正しい値として送られます。

signup.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>登録</title>
    <h1>登録情報を入力</h1>
</head>
<body>
    <h2>{{ message }}</h2>
    <form method="POST" action="/registrate">
        {{ form.csrf_token }}
        {{ form.hidden_tag() }}
        <!-- 名前 -->
        <div style="margin: 10px;">
            {{ form.name.label }}</br>
            {% if form.name.errors %}
            <span style="color: red;">{{ form.name.errors[0] }}</span></br>
            {% endif %}
            {{ form.name(placeholder="田中太郎") }}
        </div>
        <!-- パスワード -->
        <div style="margin: 10px;">
            {{ form.password.label }}</br>
            {% if form.password.errors %}
            <span style="color: red;">{{ form.password.errors[0] }}</span></br>
            {% endif %}
            {{ form.password(placeholder="8文字以上25字以下") }}
        </div>
        <!-- 性別 -->
        <div style="margin: 10px;">
            {{ form.gender.label }}</br>
            {% if form.gender.errors %}
            <span style="color: red;">{{ form.gender.errors[1] }}</span></br>
            {% endif %}
            {% for subgender in form.gender %}
            <tr>
                <td>
                    {{ subgender}}
                </td>
                <td>
                    {{ subgender.label }}
                </td>
            </tr>
            {% endfor %}
        </div>
        <!-- 生まれ年 -->
        <div style="margin: 10px;">
            {{ form.birth.label }}</br>
            {% if form.birtherrors %}
            <span style="color: red;">{{ form.birth.errors[0] }}</span></br>
            {% endif %}
            {{ form.birth}}
        </div>
        <!-- 取得資格 -->
        <div style="margin: 10px;">
            取得資格</br>
            {{ form.shikaku1 }}
            {{ form.shikaku1.label }}
            </br>
            {{ form.shikaku2 }}
            {{ form.shikaku2.label }}
            </br>
        </div>
        <div style="margin: 10px;">
            <input type="submit" value="送信">
        </div>
    </form>
</body>
</html>
index.py
@app.route('/')
def signup():
    """会員登録ページを表示"""
    form = signup_form(request.form)

    return render_template(
        'signup.html',
        form=form
    )

@app.route('/registrate', methods=['POST'])
def registrate():
    """登録情報を受け取る"""
    form = signup_form()
    if form.validate_on_submit():
       # validateを通過したら
       name = form.name.data,
       password = form.password.data,
       gender = form.gender.data,
       birth = form.birth.data,  
       if form.shikaku1.data != 0:
           shikaku1 = form.shikaku1.data
       if form.shikaku2.data != 0:
           shikaku2 = form.shikaku2.data
           return redirect('/')
    # validat通過できなければ入力フォームに戻す
    message = "バリデーションによる阻止"
    return render_template(
        "signup.html",
        form=form,
        message=message
    )

ちなみに、入力フォームに最初から値を入れておきたい場合(placeholderではなくvalueの方)
form.変数名.data = 表示させたい値 と書いておくといい。

index.py
@app.route('/')
def signup():
    """会員登録ページを表示"""
    form = signup_form(request.form)

    form.name.data = '田中太郎'
    form.gender.data = '1'
    form.birth.data = '2021'
    form.shikaku1.data = True # checked
    form.shikaku2.data = False

    return render_template(
        'signup.html',
        form=form
    )

BooleanFieldは名前の通りbool値を返すフィールド。
チェックがあればTrue,チェックがなければFalseを返します。

今回はsignup_form()という関数を作りましたが、例えば入力項目を減らしてログインフォームなどに流用しようとすると、validation関数のところで引っかかってエラーになります。

参考にした記事など

FlaskFormで簡単にバリデーションする方法 https://qiita.com/kotamatsuoka/items/c93129f6ade5974dc122
【Python】Flask+WTFormsで簡単にフォームを作成する https://hirahira.blog/flask-wtforms/
Flask Form Validation with Flask-WTF https://stackabuse.com/flask-form-validation-with-flask-wtf/
WTForm公式ドキュメント https://wtforms.readthedocs.io/en/2.3.x/

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4