pip install flask-wtf
preventing from CSRF attack
CSFR 곡격μ μ
μμ μΉμ¬μ΄νΈμμ ν¬μμκ° λ‘κ·ΈμΈν λ€λ₯Έ μΉμ¬μ΄νΈλ‘ 리νμ€νΈλ₯Ό μ μ‘ν λ μΌμ΄λλ€.
μ΄λ₯Ό μν΄ Flask-WTFλ μνΈν ν€λ₯Ό μ€μ νκΈ° μν μ ν리μΌμ΄μ
μ΄ νμνλ€.
μ΄ ν€λ₯Ό μ¬μ©νμ¬ μνΈνλ ν ν°μ μμ±νκ³ μ΄ ν ν°μ νΌ λ°μ΄ν°μ ν¨κ» 리νμ€νΈ μΈμ¦μ κ²μ¦νλλ° μ¬μ©λλ€.
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config λμ λ리λ νλ μμν¬, νμ₯ νΉμ μ ν리μΌμ΄μ μ체μμ μ¬μ©νλ μ€μ λ³μλ€μ μ μ₯νκΈ° μν΄ μΌλ°μ μΌλ‘ μ¬μ©νλ 곡κ°μ΄λ€.
Flask-WTFμ μ¬μ©ν λ μΉ νΌμ Form ν΄λμ€λ‘λΆν° μμν ν΄λμ€μ μν΄ ννλλ€.
νΌμ μλ νλλ κ°κ° μ€λΈμ νΈλ‘ ννλλ€.
κ° νλλ νλ μ΄μμ κ²μ¦μ(validator)κ° λΆμ΄ μλ€.
κ²μ¦μλ μ μΆν μ
λ ₯κ°μ΄ μ¬λ°λ₯Έμ§ νμΈνλ ν¨μμ΄λ€.
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required # NULL κ°μ΄ μλμ 보μ₯
class NameForm(Form):
name = StringField('What is your name?', validator = [Required()])
submit = SubmitField('Submit')
νΌμ μλ νλλ ν΄λμ€ λ³μλ‘ μ μλλ©° κ° ν΄λμ€ λ³μλ νλ νμ
κ³Ό κ΄κ³λ μ€λΈμ νΈλ‘ ν λΉλλ€.
μλ₯Ό λ€μ΄, StringField ν΄λμ€λ νλͺ©μ type="text" μμ±μΌλ‘ νννλ€.
Form λ² μ΄μ€ ν΄λμ€λ Flask-WTF νμ₯μ μν΄ μ μλλ―λ‘ flask.ext.wtfμμ μν¬νΈλλ€. κ·Έλ¬λ νλμ κ²μ¦μλ μ§μ WTForms ν¨ν€μ§λ‘λΆν° μν¬νΈλλ€.
WTFormsμμ μ§μνλ νμ€ HTML νλμ 리μ€νΈλ μλμ κ°λ€
νλ νμ | μ€λͺ |
---|---|
StringField | ν μ€νΈ |
TextAreaField | λ€μ€ λΌμΈ ν μ€νΈ |
PasswordField | ν¨μ€μλ ν μ€νΈ |
HiddenField | μ¨κ²¨μ§ ν μ€νΈ |
DateField | datetime.date ν μ€νΈ |
DateTimeField | datetime.datetime ν μ€νΈ |
IntegerField | μ μ κ°μ ν μ€νΈ |
DecimalField | Decimal κ°μ ν μ€νΈ |
FloatField | λΆλμμμ μ κ°λ μμ ν μ€νΈ |
BooleanField | True or False |
RadioField | λΌλμ€ λ²νΌ 리μ€νΈ |
SelectField | μ ν κ°λ₯ν λλ‘λ€μ΄ 리μ€νΈ |
SelectMultipleField | λ€μ€ μ ν λλ‘λ€μ΄ 리μ€νΈ |
FileField | νμΌ μ λ‘λ νλ |
SubmitField | νΌ μ μΆ λ²νΌ |
FormField | νΌ μμ νΌ |
FieldList | μ£Όμ΄μ§ νμ μ νλ 리μ€νΈ |
WTFormsμ λ΄μ₯λμ΄ μλ κ²μ¦μμ 리μ€νΈλ μλμ κ°λ€
κ²μ¦μ | μ€λͺ |
---|---|
μ΄λ©μΌ μ£Όμ | |
EqualTo | λ νλ κ° λΉκ΅ (ν¨μ€μλ κ²μ¦) |
IPAddress | IPv4 λ€νΈμν¬ μ£Όμ |
Length | μ λ ₯ν λ¬Έμμ΄μ κΈΈμ΄λ₯Ό κ²μ¦ |
NumberRange | μ λ ₯ν κ°μ΄ μ«μμ μνλ²³ λ²μμΈμ§ κ²μ¦ |
Optional | Null κ°μ νμ©νκ³ μΆκ°ν κ²μ¦μλ₯Ό 건λλ |
Required | Null κ°μ λΆν |
Regexp | μ κ·ννμμ λν μ λ ₯μ κ²μ¦ |
URL | URLμ κ²μ¦ |
AnyOf | μ λ ₯μ΄ κ°λ₯ν κ°λ€ μ€ νλμΈμ§λ₯Ό κ²μ¦ |
NoneOf | μ λ ₯μ΄ λΆκ°ν κ°λ€ μ€ νλκ° μλλΌλ κ²μ κ²μ¦ |
νΌ νλλ νΈμΆμ΄ κ°λ₯νλ€.
Flask-Bootstrapμ μ 체 Flask-WTF νΌμ λ λλ§νκΈ° μν΄ λΆνΈμ€νΈλ©μ 미리 μ μλ νΌ μ€νμΌμ μ¬μ©νλλ‘ μλΉν μμ λ 벨μ ν¬νΌ ν¨μλ₯Ό μ 곡νλ€.
<form method="POST">
{{ form.name.label }} {{ form.name() }}
{{ form.submit() }}
</form>
<!-- μμλλ κ°μ κ²μ΄λ€ -->
{% import "bootstrap/wtf.html' as wtf %}
{{ wtf.quick_form(form) }}
app.routeμ methodsλ₯Ό λ±λ‘νμ§ μμΌλ©΄, ν΄λΉ λ·° ν¨μλ GET 리νμ€νΈλ§ μ²λ¦¬νλ€.
validate_on_submit()μ νΌμ΄ μ μΆλ λ Trueλ₯Ό λ°ννλ€.
@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)
μΉ μ΄ν리μΌμ΄μ μ΄ λΈλΌμ°μ μ μν΄ μ μ‘λ λ§μ§λ§ 리νμ€νΈλ‘ POST 리νμ€νΈλ₯Ό λ¨κ²¨ λμ§ μλλ‘ νλ μ΅κ΄μ λ€μΌ νμκ° μλ€. (POST/REDIRECT/GET Pattern)
μ΄ μ΅κ΄μ μ μμ μΈ μλ΅ λμ μ 리λ€μ΄λ νΈμ ν¨κ» POST 리νμ€νΈμ λν΄ μλ΅νλ κ²μ΄λ€.
κ·Έλ μ§ μμΌλ©΄ μ΄μ μ μ μΆν requestλ₯Ό νμ΄μ§κ° κΈ°μ΅νμ¬ μλ‘κ³ μΉ¨μ μνν μ, λ€μ νλ² λκ°μ 리νμ€νΈκ° μ μΆλλ λ¬Έμ λ₯Ό μΌμΌν¨λ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μνμ¬ POST/REDIRECT/GET ν¨ν΄μΌλ‘ λ¬Έμ λ₯Ό ν΄κ²°ν μ μλ€.
κ·Έλ°λ° μ΄ λν κΈ°μ‘΄μ μ μ₯λ μ¬μ©μ μ 보λ₯Ό μμ΄λ²λ¦΄ μ μλ€λ λ¬Έμ μ μ΄ μλ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ μ¬μ©μ μΈμ
μ μ¬μ©ν μ μλ€.
#hello.py
from flask import Flask, render_template, session, redirect, url_for
@app.route('/', methods=['GET','POST'])
def index():
form = NameForm()
if form.validate_on_submit():
session['name'] = form.name.data
return redirect(url_for('index'))
return render_template('index.html', form=form, name=session.get('name'))
λλ‘λ 리νμ€νΈλ₯Ό μλ£νκ³ λμ μ¬μ©μμκ² μν μ
λ°μ΄νΈλ₯Ό μ λ¬νλ κ²μ΄ μ μ©νλ€.
μ΄λ λ‘κ·ΈμΈ μλμ λ°λ₯Έ μλ΅ λ©μμ§λ₯Ό μ λ¬ν΄μΌ νλ κ²½μ°μ΄λ€.
μ΄λ₯Ό μν΄ νλΌμ€ν¬λ flash() ν¨μλ₯Ό μ 곡νλ€.
from flask import Flask, render_template, session, redirect, url_for, flash
@app.route('/'. methods=['GET','POST']
def index():
form = NameForm()
if form.validate_on_submit():
old_name = session.get('name')
if old_name is not None and old_name != form.name.data:
flash('Looks like you have changed your name!')
session['name'] = form.name.data
form.name.data = ''
return redirect(url_for('index'))
return render_template('index.html', form = form, name = session.get('name'))
κ·Έλ°λ° μ΄λ κ² flash()λ₯Ό νΈμΆνλ κ²λ§μΌλ‘λ λ©μΈμ§λ₯Ό μΆλ ₯νκΈ°μ μΆ©λΆνμ§ μλ€.
λ² μ΄μ€ ν
νλ¦Ώμ νμ©νμ¬ λͺ¨λ νμ΄μ§μμ 보μ¬μ§ μ μλλ‘ λ§λ€μ΄μΌ νκΈ° λλ¬Έμ΄λ€.
get_flashed_messages() ν¨μλ μ΄λ₯Ό λμμ€λ€.
<!-- template/base.html -->
{% block content %}
<div class='container'>
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">
×
</button>
{{ message }}
</div>
{% endfor %}
{% block page_content %}
{% endblock %}
</div>
{% endblock %}