20201106-第十二讲-Flask-补充WTForms表单验证、cookie的基本使用

Flask-补充WTForms表单验证

Flask-WTF

Flask-WTF是简化了WTForms操作的一个第三方库。WTForms表的二个主要功能是验证用户提交数据的合法性以及渲染模板。当然还包括一些其他功能:CSRF保护,文件上传等。安装Flask-WTF默认也会安装WTForms,因此使用以下命令安装Flask-WTF

1 pip install flask-wtf

表单验证

安装完Flask-WTF后,来看下第一个功能,就是用表单来做数据验证,现在有一个forms.py文件,然后再里面创建一个RegistForm的注册验证表单

1 class RegistForm(Form):

2        name = StringField(validators=[length(min=4,max=25)])

3        email = StringField(validators=[email()])

4        password = StringField(validators=[DataRequired(),length(min=6,max=10),EqualTo('confirm')])

5        confirm = StringField()

在这个表单里面指定需要上传的参数,且指定了验证器,比如name的长度应该在4-25之间。email必须要满足邮箱的格式。password长度必须在6-10之间,并且应该和confirm相等才能通过验证

写完表单后,接下来就是regist.html文件

1 <form action="/regist/" method="POST">

2        <table>

3              <tr>

4                  <td>用户名:</td>

5                  <td><input type="text" name="name"></td>

6              </tr>

7              <tr>

8                  <td>邮箱:</td>

9                  <td><input type="email" name="email"></td>

10            </tr>

11            <tr>

12                  <td>密码:</td>

13                  <td><input type="password" name="password"></td>

14            </tr>

15            <tr> 

16                <td>确认密码:</td>

17                <td><input type="password" name="confirm"></td>

18            </tr>

19            <tr>

20                 <td></td>

21                <td><input type="submit" value="提交"></td>

22            </tr>

23        </table>

24 </form>

再来看视图函数regist

1 @app.route('/regist/',methods=['POST','GET'])

2 def regist():

3        form = RegistForm(request.form)

4        if request.method == 'POST' and form.validate():

5              user = User(name=form.name.data,email=form.email.data,password=form.password.data)

6              db.session.add(user)

7              db.session.commit()

8              return '注册成功!'

9        return render_template('regist.html')

RegistForm传递的是request.form进去进行初始化,并且判断form.validate会返回用户提交的数据是否满足表单的验证

渲染模板

form还可以渲染模板,让你少写了一些代码,比如重写以上例子,RegistForm表单代码如下

1 class RegistForm(Form):

2        name = StringField('用户名:',validators=[length(min=4,max=25)])

3        email = StringField('邮箱:'validators=[email()])

4        password = StringField('密码:',validators=[DataRequired(),length(min=6,max=10),EqualTo('confirm')])

5        confirm = StringField('确认密码:')

以上增强了第一个位置参数,用来在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 '注册成功!'

    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>

文件上传

1.在模板中,form表单中,需要指定encotype='multipart/form-data'才能上传文件。

2.在后台如想要获取上传文件,那么应该使用request.files.get(’avatar')来获取。

3.保存文件之前,先要使用werkzeug.utils.secure_filename来对上传上来的文件名进行一个过滤。这样才能保证不会有安全问题。

4.获取到上传上来的文件后,使用avatar.save(路径)方法来保存文件。

5.从服务器上读取文件后,应该定义一个url与视图函数,来获取指定的文件。在这个视图函数中,使用send_from_directory(文件的目录,文件名)来获取。

@app.route('/upload/',methods=['GET','POST'])

def upload():

    if request.method == 'GET':

        return render_template('upload.html')

    else:

        # 获取描述信息

        desc = request.form.get("desc")

        avatar = request.files.get("avatar")

        filename = secure_filename(avatar.filename)

        avatar.save(os.path.join(UPLOAD_PATH,filename))

        print(desc)

        return '文件上传成功'

@app.route('/images/<filename>/')

def get_image(filename):

    return send_from_directory(UPLOAD_PATH,filename)

对上传文件使用表单验证:

1.定义表单时,对文件的字段,需要采用FileField这个类型。

2.验证器应该从flask_wtf.file中导入。flask_wtf.file.FileRequired是用来验证文件上传是否为空。flask_wtf.file.FileAllowed用来验证上传的文件的后缀名。

3.在视图文件中,使用from werkzeug.datastructures import CombinedMultiDict来把request.form与request.files 来进行合并。再传给表单来验证。

1 from werkzeug.datastructures import CombinedMultiDict

2 form = UploadForm(CombinedMultiDict([request.form,request.files]))


cookie和session

1.cookie:在网站中,http请求是无状态的。即使第一次和服务器连接后且登录成功后,第二次请求服务器依然不能知道当前请求是那个用户。cookie的出现就是为了解决此问题,第一次登录后服务器返回数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求时,就会自动把上次请求存贮的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是那个了。cookie存贮的数据量有限,不同的浏览器有不同的储存大小,但一般不超过4KB。因此使用cookie只能储存一些小量的数据。

2.session:session和cookie的作用有点类似,都是为了储存用户相关的信息。不同的是,cookie是储存在本地浏览器,session是一个思路、一个概念、一个服务器储存授权信息的解决方案,不同的框架,不同的语言有不同的实现。虽然实现不一样,但他们的目的都是服务器为了方便存储数据的。session的出现,是为了解决cookie存储不安全的问题的。

3.cookie和session结合使用: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采用的就是这种方式,但也可以替换成其他形式。

flask中使用cookie和session

1.cookie:在Flask中操作cookie,是通过response对象来操作,可以在response返回之前,通过response.set_cookie来设置,这个方法有一下几个参数需要注意:

key:设置的cookie的key。

value:key对应的value。

max_age:改cookie的过期时间,如果不设置,则浏览器关闭后就会自动过期。

expires:过期时间,应该是一个datetime类型

domain:该cookie在那个域名中有效。一般设置子域名,比如cms.example.com。

path:该cookie在哪个路径下有效。

2.session:Flask中的session是通过from flask import session。然后添加值key和value进去既可。并且,Flask中的session机制是将session信息加密,然后存储在cookie中。专业术语叫client side session。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。