LoginSignup
2
2

More than 3 years have passed since last update.

Flask-WTFでWebフォームを作る

Posted at

Flask-WTFはPythonでWebフォームとそのバリデーションを簡単に実装できるフレームワークWTFormsのFlask版です。

まずはインストール

pip install flask-wtf

次に秘密鍵を設定をします。
Flaskで作成するアプリの設定はFlaskクラスのインスタンス(ここではapp)の.configに設定します。

app.config['SECRET KEY'] = 'hard to guess string'

今回はソースコードにベタ打ちしてますが、商用のアプリケーションなどでは環境変数から取得したり、端末ごとに変えたりする必要があります。
Flask-WTFではこの秘密鍵をCSRF攻撃などへの対策として利用します。

CSRF攻撃はざっくりとログイン状態にある(セッションにログイン情報を保持している)ユーザーが悪意のあるサイトにアクセスすることで、不正なリクエストがフォーム経由などで送信されるものです。
アカウント乗っ取りやなりすまし投稿などが被害例としてあります。

Flask-WTFでは正しいフォームからのリクエストなのかを確認するためにセキュリティトークンを発行し、ユーザーセッションの中にその情報を格納しますが、その際の暗号化に秘密鍵が使用されます。

では実際にフォームを作ります。
Flask-WTFではフォームをFlaskFormクラスを継承したクラスとして定義し、各項目をクラス変数として定義します。
なお各項目は入力されるデータ形式(string型など)ごとにwtformsが用意するFieldクラスのインスタンスとして作成されます。
※例えばStringField型の場合はhtmlでいうところのinput要素でtype="text"を指定した状態になります。

from flask_wtf import FlaskForm
from wtforms import StringFields, SubmitField
from wtforms.validators import DataRequired

class NameForm(FlaskForm):
    name = StringField('What is your name?', validators = [DataRequired()])
    submit = SubmitField('submit')

Field型のオブジェクトは最初の引数に項目名(htmlでいうところのlabelに対応)をとることができます。
また上記の例ではバリデーターとしてDataRequiredを指定しています。これによってこの項目が入力されていない場合、フォームの送信がさせないようにすることができます。

あとはこのクラスを利用して、view関数経由でテンプレートをレンダリングする際にフォームオブジェクトを変数として渡してあげればOKです。

@app.route('/', methods = ['GET', 'POST']
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html', form = form, name = name)

変数nameにNoneを代入することで初期化し、NameFormクラスのインスタンスとして変数formを作ります。
NameFormクラスの(厳密にはFlaskFormクラスの)メソッドvalidate_on_submit()で先ほど設定してバリデーションを行います。
正の場合にはform.name.dataで入力されたデータを取得して変数nameに格納し、フォームのデータ自体は空文字でクリアします。
そうすることで再度フォームを読み込んだ際に入力されたデータをリセットすることができます。

テンプレートは下記です。

<div class="page-header">
    <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1>
</div>

<form method="POST">
    {{ form.hidden_tag() }}
    {{ form.name.label }} {{ form.name }}
    {{ form.submit }}
</form>

変数nameがNoneではない場合はその名前を表示し、Noneである場合にはStrangerを表示します。
フォーム自体はhtmlのform要素で作成し、中身をview関数から受け取ったformの各変数として書いてあげることでフォームを作ることができます。

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