Flask-WTF
是简化了WTForms
操作的一个第三方库。WTForms
表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。当然还包括一些其他的功能:CSRF保护
,文件上传等。安装Flask-WTF
默认也会安装WTForms
,因此使用以下命令来安装Flask-WTF
:
pip install flask-wtf
安装完Flask-WTF
后。来看下第一个功能,就是用表单来做数据验证,现在有一个forms.py
文件,然后在里面创建一个RegistForm
的注册验证表单:
class RegistForm(Form):
name = StringField(validators=[length(min=4,max=25)])
email = StringField(validators=[email()])
password = StringField(validators=[DataRequired(),length(min=6,max=10),EqualTo(‘confirm‘)])
confirm = StringField()
在这个里面指定了需要上传的参数,并且指定了验证器,比如name
的长度应该在4-25
之间。email
必须要满足邮箱的格式。password
长度必须在6-10
之间,并且应该和confirm
相等才能通过验证。
写完表单后,接下来就是regist.html
文件:
<form action="/regist/" method="POST">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="email" name="email"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>确认密码:</td>
<td><input type="password" name="confirm"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
再来看视图函数regist
:
@app.route(‘/regist/‘,methods=[‘POST‘,‘GET‘])
def regist():
form = RegistForm(request.form)
if request.method == ‘POST‘ and form.validate():
user = User(name=form.name.data,email=form.email.data,password=form.password.data)
db.session.add(user)
db.session.commit()
return u‘注册成功!‘
return render_template(‘regist.html‘)
RegistForm
传递的是request.form
进去进行初始化,并且判断form.validate
会返回用户提交的数据是否满足表单的验证。
form
还可以渲染模板,让你少写了一丢丢的代码,比如重写以上例子,RegistForm
表单代码如下:
class RegistForm(Form):
name = StringField(u‘用户名:‘,validators=[length(min=4,max=25)])
email = StringField(u‘邮箱:‘validators=[email()])
password = StringField(u‘密码:‘,validators=[DataRequired(),length(min=6,max=10),EqualTo(‘confirm‘)])
confirm = StringField(u‘确认密码:‘)
以上增加了第一个位置参数,用来在html文件中,做标签提示作用。
在app
中的视图函数中,修改为如下:
@app.route(‘/regist/‘,methods=[‘POST‘,‘GET‘])
def regist():
form = RegistForm(request.form)
if request.method == ‘POST‘ and form.validate():
user = User(name=form.name.data,email=form.email.data,password=form.password.data)
db.session.add(user)
db.session.commit()
return u‘注册成功!‘
return render_template(‘regist.html‘,form=form)
以上唯一的不同是在渲染模板的时候传入了form
表单参数进去,这样在模板中就可以使用表单form
变量了。
接下来看下regist.html
文件:
<form action="/regist/" method="POST">
<table>
<tr>
<td>{{ form.name.label }}</td>
<td>{{ form.name() }}</td>
</tr>
<tr>
<td>{{ form.email.label }}</td>
<td>{{ form.email() }}</td>
</tr>
<tr>
<td>{{ form.password.label }}</td>
<td>{{ form.password() }}</td>
</tr>
<tr>
<td>{{ form.confirm.label }}</td>
<td>{{ form.confirm() }}</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
在使用Field
的时候,经常需要传递一些参数进去,以下将对一些常用的参数进行解释:
Field
的label的文本。Field
的id属性,默认不写为该属性名。html
控件。BooleanField:布尔类型的Field,渲染出去是checkbox
。
FileField:文件上传Field。
# forms.py
from flask_wtf.file import FileField,FileAllowed,FileRequired
class UploadForm(FlaskForm):
avatar = FileField(u‘头像:‘,validators=[FileRequired(),FileAllowed([])])
# app.py
@app.route(‘/profile/‘,methods=(‘POST‘,‘GET‘))
def profile():
form = ProfileForm()
if form.validate_on_submit():
filename = secure_filename(form.avatar.data.filename)
form.avatar.data.save(os.path.join(app.config[‘UPLOAD_FOLDER‘],filename))
return u‘上传成功‘
return render_template(‘profile.html‘,form=form)
FloatField:浮点数类型的Field,但是渲染出去的时候是text
的input。
IntegerField:整形的Field。同FloatField。
RadioField:radio
类型的input
。表单例子如下:
# form.py
class RegistrationForm(FlaskForm):
gender = wtforms.RadioField(u‘性别:‘,validators=[DataRequired()])
模板文件代码如下:
<tr>
<td>
{{ form.gender.label }}
</td>
<td>
{% for gender in form.gender %}
{{ gender.label }}
{{ gender }}
{% endfor %}
</td>
</tr>
app.py
文件的代码如下,给gender
添加了choices
:
@app.route(‘/register/‘,methods=[‘POST‘,‘GET‘])
def register():
form = RegistrationForm()
form.gender.choices = [(‘1‘,u‘男‘),(‘2‘,u‘女‘)]
if form.validate_on_submit():
return u‘success‘
return render_template(‘register.html‘,form=form)
SelectField:类似于RadioField
。看以下示例:
# forms.py
class ProfileForm(FlaskForm):
language = wtforms.SelectField(‘Programming Language‘,choices=[(‘cpp‘,‘C++‘),(‘py‘,‘python‘),(‘text‘,‘Plain Text‘)],validators=[DataRequired()])
再来看app.py
文件:
@app.route(‘/profile/‘,methods=(‘POST‘,‘GET‘))
def profile():
form = ProfileForm()
if form.validate_on_submit():
print form.language.data
return u‘上传成功‘
return render_template(‘profile.html‘,form=form)
模板文件为:
<form action="/profile/" method="POST">
{{ form.csrf_token }}
{{ form.language.label }}
{{ form.language() }}
<input type="submit">
</form>
StringField:渲染到模板中的类型为``,并且是最基本的文本验证。
PasswordField:渲染出来的是一个password
的input
标签。
TextAreaField:渲染出来的是一个textarea
。
数据发送过来,经过表单验证,因此需要验证器来进行验证,以下对一些常用的内置验证器进行讲解:
InputRequired
。URL
的形式。UUID
。使用validate_fieldname(self,field)
可以对某个字段进行更加详细的验证,如下:
class ProfileForm(FlaskForm):
name = wtforms.StringField(‘name‘,[validators.InputRequired()])
def validate_name(self,field):
if len(field.data) > 5:
raise wtforms.ValidationError(u‘超过5个字符‘)
在flask的表单中,默认是开启了csrf
保护功能的,如果你想关闭表单的csrf
保护,可以在初始化表单的时候传递csrf_enabled=False
进去来关闭csrf
保护。如果你想关闭这种默认的行为。如果你想在没有表单存在的请求视图函数中也添加csrf
保护,可以开启全局的csrf
保护功能:
csrf = CsrfProtect()
csrf.init_app(app)
或者是针对某一个视图函数,使用csrf.protect
装饰器来开启csrf
保护功能。并且如果已经开启了全局的csrf
保护,想要关闭某个视图函数的csrf
保护功能,可以使用csrf.exempt
装饰器来取消本视图函数的保护功能。
在AJAX
中要使用csrf
保护,则必须手动的添加X-CSRFToken
到Header
中。但是CSRF
从哪里来,还是需要通过模板给渲染,而Flask
比较推荐的方式是在meta
标签中渲染csrf
,如下:
<meta name="csrf-token" content="{{ csrf_token() }}">
如果要发送AJAX
请求,则在发送之前要添加CSRF
,代码如下(使用了jQuery):
var csrftoken = $(‘meta[name=csrf-token]‘).attr(‘content‘)
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})
cookie
的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie
数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie
存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie
只能存储一些小量的数据。cookie
是存储在本地浏览器,session
是一个思路、一个概念、一个服务器存储授权信息的解决方案,不同的服务器,不同的框架,不同的语言有不同的实现。虽然实现不一样,但是他们的目的都是服务器为了方便存储数据的。session
的出现,是为了解决cookie
存储数据不安全的问题的。web
开发发展至今,cookie
和session
的使用已经出现了一些非常成熟的方案。在如今的市场或者企业里,一般有两种存储方式:
cookie
存储一个session_id
,然后具体的数据则是保存在session
中。如果用户已经登录,则服务器会在cookie
中保存一个session_id
,下次再次请求的时候,会把该session_id
携带上来,服务器根据session_id
在session
库中获取用户的session
数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session
。存储在服务器的数据会更加的安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但现在服务器已经发展至今,一些session
信息还是绰绰有余的。session
数据加密,然后存储在cookie
中。这种专业术语叫做client side session
。flask
采用的就是这种方式,但是也可以替换成其他形式。cookies:在Flask
中操作cookie
,是通过response
对象来操作,可以在response
返回之前,通过response.set_cookie
来设置,这个方法有以下几个参数需要注意:
datetime
类型。cms.example.com
。Flask
中的session
是通过from flask import session
。然后添加值key和value进去即可。并且,Flask
中的session
机制是将session
信息加密,然后存储在cookie
中。专业术语叫做client side session
。flask全栈开发8 Flask-WTF和cookie和session
原文:https://www.cnblogs.com/sky-ai/p/12830549.html