flask에서 form을 관리할 수 있는 기능을 제공해주는 package이다.
form이란 사용자로부터 정보를 입력받는 방식을 말한다.
사용하기 위해서 dependency를 추가해준다.
$> poetry add Flask-WTF
원하는 form을 사용하기 위해서는 flask-wtf에서 제공하는 FlaskForm 클래스를 상속 받아서 클래스를 생성하면 된다.
flask-wtf을 사용함을 통해서 제공받을 수 있는 기능은 다음과 같다.
validators
를 사용하여 입력 받은 값에 대한 유효성 검사가 가능auth/form.py 👇
from flask_wtf import FlaskForm
from wtforms import StringField, validators, PasswordField, BooleanField
class RegisterForm(FlaskForm):
username = StringField('Username', [validators.Length(min=4, max=25)])
# email format에 대한 유효성 검사를 위해서는 추가적으로 email_validator package를 추가해야함
email = StringField('Email', [validators.DataRequired()])
password = PasswordField('New Password', [
validators.DataRequired(),
validators.EqualTo('password_confirm', message='Passwords must be matched'),
])
password_confirm = PasswordField('Repeat Password')
accept_tos = BooleanField('I accept the TOS', [validators.InputRequired()])
사용할 form을 만들어주었다면 해당 form을 입력 받을 endpoint를 작성해준다.
이 때, 생성한 form 클래스의 instance를 선언해주고 해당 인스턴스로부터 데이터를 받아온다.
선언한 form 클래스의 instance는 template을 보여줄 때 form parameter의 값으로 넘겨줘야 template에서 form으로 받은 값을 사용할 수 있다.
auth/__init__.py 👇
from login.auth.form import RegisterForm
@auth.route('/register', methods=['GET', 'POST'])
def register():
# 회원가입
form = RegisterForm()
if request.method == 'POST':
if form.validate_on_submit():
username = form.data.get('username')
email = form.data.get('email')
password = form.data.get('password')
user = User()
user.email = email
user.name = username
user.password = password
db.session.add(user)
db.session.commit()
# 알림 메세지를 띄우기 위함 >> 필수X
flash('회원 가입이 완료되었습니다.')
return redirect(url_for('index'))
else:
flash('입력한 값을 확인해주세요.')
# 생성한 form instance template에 넘겨주기
return render_template('auth/register.html', form=form)
flask에서는 jinja2를 이용해서 html를 구성할 수 있기 때문에 {{ }}
의 format을 통해서 변수값을 사용해 화면에 표시할 수 있다.
/templates/auth/register.html 👇
<form method="post">
{{ form.csrf_token }}
<div>
{{ form.username.label() }}
{{ form.username() }}
</div>
<div>
{{ form.email.label() }}
{{ form.email() }}
</div>
<div>
{{ form.password.label() }}
{{ form.password() }}
</div>
<div>
{{ form.password_confirm.label() }}
{{ form.password_confirm() }}
</div>
<div>
{{ form.accept_tos.label() }}
{{ form.accept_tos() }}
</div>
<div>
<button type="submit" class="btn btn-primary">Register</button>
</div>
</form>
위와 같은 코드로 작성을 했지만 실제로는 다음과 같이 랜더링된다.
해당 페이지로 접근할 시 화면에는 다음과 같이 나타나게 된다.
form에서 제공하는 validators
를 사용해 유효성 검증을 했기 때문에, 추가적인 과정 없이 설정한 validation과 맞지 않으면 다음과 같이 alert pop up들이 제공된다.
CSRF는 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격을 말한다.
flask-WTF을 사용한다면 이런 공격에 대한 방지를 할 수 있다.
CSRFProtected()
instance를 생성csrf = CSRFProtected()
csrf.init_app(app)
을 통해 간단하게 사용해볼 수 있다.