Python + Flaskを使ったWebアプリ作成②(入力フォーム編)








上記の記事「Python + Flaskを使ったWebアプリ作成①(環境構築〜画面追加編)」の続きです。
今回はログイン画面と登録画面の入力フォームを作成します。



*参考



*Flask WTF のインストール

flask-wtfを使うとバリデーションなどを行うフォームを簡単に作成することができます。これをインストールします。
$ pip install flask-wtf


*Formの作成

ログイン画面と登録画面の入力フォームを作成します。
文字列の入力フォームはStringField、パスワードの入力フォームはPasswordFieldなど入力項目ごとにFieldクラスを指定します。

また、Fieldにはバリデーションを指定することができます。
  • DataRequired() --> 必須項目
  • Length(min, max) --> 文字数制限
  • Email() --> 電子メール形式の文字列のみ許可
  • EqualTo --> 等しい値のみ許可
<forms.py>
from flask_wtf import FlaskForm  
from wtforms import StringField, PasswordField, SubmitField, BooleanField  
from wtforms.validators import DataRequired, Length, Email, EqualTo  
  
  
class RegistrationForm(FlaskForm):  
    username = StringField('Username',  
                           validators=[DataRequired(), Length(min=2, max=20)])  
    email = StringField('Email',  
                        validators=[DataRequired(), Email()])  
    password = PasswordField('Password', validators=[DataRequired()])  
    confirm_password = PasswordField('Confirm Password',  
                                     validators=[DataRequired(), EqualTo('password')])  
    submit = SubmitField('Sign Up')  
  
  
class LoginForm(FlaskForm):  
    email = StringField('Email',  
                        validators=[DataRequired(), Email()])  
    password = PasswordField('Password', validators=[DataRequired()])  
    remember = BooleanField('Remember me')  
    submit = SubmitField('Login')



*シークレットキーの作成

Flaskでは標準でシークレットキーを使うことができます。
セッションの内容を署名つきでCookieに保存します。
このシークレットキーの値が漏れない限り、セッションを改ざんすることはできません。

ターミナルでセッションを作成します。
$ python
>>> import secrets
>>> secrets.token_hex(16)
'cfb33786023cc152019e747a051f73c6'

登録ボタンとログインボタン押下時の処理を追加します。
validate_on_submit()でPOSTリクエストかをチェックすることができます。

<home.py>
from datetime import datetime  
from flask import Flask, render_template, url_for, flash, redirect  
from forms import RegistrationForm, LoginForm  
  
app = Flask(__name__)  
  
app.config['SECRET_KEY'] = 'cfb33786023cc152019e747a051f73c6'  
  
    
posts = [  
    {  
        'author': 'Corey Schafer',  
        'title': 'Blog Post 1',  
        'content': 'First post content',  
        'date_posted': 'April 20, 2018'  
  },  
    {  
        'author': 'Jane Doe',  
        'title': 'Blog Post 2',  
        'content': 'Second post content',  
        'date_posted': 'April 21, 2018'  
  }  
]  
  
  
@app.route('/')  
@app.route('/home')  
def home():  
    return render_template('home.html', posts=posts)  
  
  
@app.route('/about')  
def about():  
    return render_template('about.html', title='About')  
  

# ----- 追加 -----
@app.route('/register', methods=['GET', 'POST'])  
def register():  
    form = RegistrationForm()  
    if form.validate_on_submit():  
        # POSTリクエスト(登録時)
        flash('Account created for %s!' % form.username.data, 'success')  
        return redirect(url_for('home'))  
    # 初期表示時    
    return render_template('register.html', title='Register', form=form)  
  

# ----- 追加 -----
@app.route('/login', methods=['GET', 'POST'])  
def login():  
    form = LoginForm()  
    if form.validate_on_submit():  
        # POSTリクエスト(ログイン時)
        if form.email.data == 'admin@blog.com' and form.password.data == 'password':  
            flash('You have been logged in!', 'success')  
            return redirect(url_for('home'))  
        else:  
            flash('Login Unsuccessful. Please check username and password', 'danger')  
    # 初期表示時
    return render_template('login.html', title='Login', form=form)  
  
  
if __name__ == '__main__':  
    app.run(debug=True)


*ログイン画面

入力エラー










登録成功









*登録画面

入力エラー










登録成功











*所感

WTFについての日本語のドキュメントがなく情報は少なかったですが、基本的なことはすぐに理解できますし、特にEmailのバリデーションが備わっているのが便利だったので実用的かと思います。
POSTとGETのリクエストを同じメソッドにしてvalidate_on_submit()で処理を分けるとコードが少なくなりそうですが、個人的には分けたメソッドにしたほうがわかりやすいかと思いました。validate_on_submit()でリクエストの判定ができることを初めて知ったので覚えておこうと思います。

Previous
Next Post »

3 コメント

Write コメント
匿名
AUTHOR
2020年7月5日 1:33 delete

home.pyの3行目のfrom forms import RegistrationForm, LoginFormでModuleNotFoundError: No module named 'forms'とエラーがでてしまうのですが、どのように対処いたいしたらよろしいのでしょうか。

Reply
avatar
maya
AUTHOR
2020年7月5日 22:14 delete

申し訳ありません、ファイル名を誤って記載していました。
前手順で作成したファイル名を、form.py ではなく forms.py に修正して頂ければエラーが出なくなるかと思います。

修正しておきました。
見てくださりありがとうございます。

Reply
avatar
匿名
AUTHOR
2020年7月7日 5:02 delete

返答ありがとうございました。

Reply
avatar

人気の投稿