3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Flaskでバリデーションを体験

Last updated at Posted at 2023-03-12

はじめに

本記事では、Flaskにおけるバリデーション機能の実装を体験します。
フォームに値を入力し、記述通りに処理が実行されるかを確認します。

前提

  • Flaskオブジェクトを生成できる
  • リクエストを受け取る方法を知っている

バリデーションとは

バリデーションとは、データの入力に制限を付加する機能のことです。

例えば、サイトの会員登録フォームに入力するパスワードに英数字大文字の使用が必須であったとします。
このフォームに全て小文字のアルファベットでパスワードを入力をした場合、条件を満たしていないことを警告するメッセージが表示されて送信が中断するはずです。
このときに実行される、条件を満たしているかどうかの確認処理がバリデーションです。

作成アプリイメージ

作成アプリでは、文字列とテキストの入力フォームを用意し、それぞれに入力制限を実装していきます。

  • バリデーションOK
    通過.gif

  • バリデーションNG
    不通過.gif

実践

フォルダ構成

今回作成するアプリのフォルダ構成を確認します。

.
├── app.py
├── form.py
└── templates
    └── index.html
  • 「app.py」
    • ルーティングを記述します。
  • 「form.py」
    • ブラウザに表示するフォーム、バリデーションの処理を記述します。
  • 「index.html」
    • ブラウザに表示する内容を記述します。

ライブラリインストール

以下コマンドでライブラリをインストールします。

pip install Flask Flask-WTF WTForms
  • Flask-WTF
    • Flaskアプリで、ブラウザのフォームとバリデーションを実装するための機能を提供するライブラリ
  • WTForms
    • バリデーションの中で使用する部品を提供するライブラリ

各ライブラリの違いを一言で説明することは難しいのですが、本記事内ではこのような使い分けをします。

ファイル作成

form.py

以下を記述します。

form.py
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, ValidationError

class Form(FlaskForm):
    string = StringField('文字列')
    text = TextAreaField('テキスト')
    
    def validate_string(self, string):
        '''
        - 未入力 禁止
        - 文字数9文字以上 禁止
        - 「-」 禁止
        '''
        if string.data == '':
            raise ValidationError('値を入力してください。')
        
        if len(string.data) > 8:
            raise ValidationError('値を8文字以内で入力してください。')
        
        if '-' in string.data:
            raise ValidationError('「-」の入力は禁止されています。')
    
    def validate_text(self, text):
        '''
        - 未入力 禁止
        - 文字数20文字未満 禁止
        '''
        if text.data == '':
            raise ValidationError('値を入力してください。')
        
        if len(text.data) < 20:
            raise ValidationError('値を20文字以上入力してください。')

説明

from flask_wtf import FlaskForm
  • FlaskForm
    • Formクラスに継承するオブジェクトです。
    • FlaskFormオブジェクトを継承したクラスは、バリデーションの機能が有効になります。
from wtforms import StringField, TextAreaField, ValidationError
  • StringField, TextAreaField
    • バリデーションの機能を持つ入力領域を定義します。
    • 他にも、IntegerField, RadioFieldなどがあります。
  • ValidationError
    • バリデーションNGのときに発生させる例外です。
    • 例外が発生することが予想される場合、raise文でValidationErrorを発生させることで、引数にしていした値をブラウザ画面に表示させます。
class Form(FlaskForm):
    string = StringField('文字列')
    text = TextAreaField('テキスト')

フォームを構成する入力フィールドを定義します。
各Fieldオブジェクトの引数に指定した値は、ブラウザ画面に入力項目名として使用できます。

def validate_string(self, string):
    if string.data == '':
        raise ValidationError('値を入力してください。')

入力フィールドstringのバリデーションです。
バリデーションの関数名は「validate_*」である必要があります。

バリデーションは、「入力フィールド名 + data」に対しての条件を記述する形で設定します。

バリデーションでTrueだった場合、つまり、制限された入力をした場合、ValidationErrorを発生させます。
ValidationErrorの引数に指定した値は、ブラウザ画面で表示させることができます。

app.py

以下を記述します。

app.py
from flask import Flask, request, render_template
from form import Form

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret_key'

@app.route('/', methods=['GET', 'POST'])
def index():
    form = Form()
    if request.method == 'GET':
        title = '値を送信してください'
        return render_template('index.html', form=form, title=title)
    
    if request.method == 'POST':
        if form.validate_on_submit():
            title = 'バリデーションを通過しました'
            return render_template('index.html', form=form, title=title)
        else:
            title = 'バリデーションを通過できませんでした'
            return render_template('index.html', form=form, title=title)
        
if __name__ == '__main__':
    app.run(debug=True)

説明

from form import Form

バリデーションを設定したFormクラスをインポートします。

if request.method == 'POST':
    if form.validate_on_submit():
        title = 'バリデーションを通過しました'
        return render_template('index.html', form=form, title=title)
    else:
        title = 'バリデーションを通過できませんでした'
        return render_template('index.html', form=form, title=title)
  • validate_on_submit()
    • バリデーションの確認をします。
    • 問題なくバリデーションを通過できれば、Trueを返します。

また、Formクラスをインスタンス化したformオブジェクトをindex.htmlに渡しています。

index.html

以下を記述します。

index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>バリデーションテスト</title>
</head>

<body>
    <h1>{{ title }}</h1>
    <form action="" method="POST">
        {{ form.hidden_tag() }}

        {{ form.string.label }}:
        <div>
            {{ form.string }}

            {% for error in form.string.errors %}
            <span style="color: red">{{ error }}</span>
            {% endfor %}
        </div>

        {{ form.text.label }}:
        <div>
            {{ form.text }}

            {% for error in form.text.errors %}
            <span style="color: red">{{ error }}</span>
            {% endfor %}
        </div>

        <input type="submit" value="送信">
    </form>
</body>

</html>

説明

  • hidden_tag()
    • FlaskFormを継承したFormクラスをブラウザ画面に表示します。
  • form.string.label
    • 入力フィールドstringの項目名を表示します。
    • この値は、form.pyのクラス定義の中で、StringFieldの引数に指定した値です。
  • form.string
    • stringの入力フィールドを表示します。
{% for error in form.string.errors %}
<span style="color: red">{{ error }}</span>
{% endfor %}

form.pyで発生させたエラーの内容を表示します。

終わりに

意外と簡単にバリデーションを実装できました。
他の入力フィールドについても試してみたいです。

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?