目录
  • 1 使用Flask处理表单
    • 1.1 使用Flask处理通用表单
    • 1.2 使用Flask-WTF处理表单
  • 2 使用Flask上传文件
    • 3 Cookie的使用
      • 3.1 Cookie的基本概念
      • 3.2 Cookie的基本使用
    • 4 Session的使用
      • 4.1 Session的基本配置
      • 4.2 Session的基本使用

    1 使用Flask处理表单

    什么是表单(Form)? 表单是搜集用户数据信息的各种表单元素的集合区域。它的作用是实现用户和服务器的数据交互。通过表单搜集客户端输入的数据信息,如何提交到网站服务器进行处理(搜集录入/比对验证等)。Form表单是Web应用中最继承的一部分。为了能处理Form表单,Flask-WTF扩展提供了良好的支持。

    1.1 使用Flask处理通用表单

    Flask请求对象包括客户端发出的所有请求信息,其中,request.form能获取POST请求中提交的表单数据。尽管Flask的请求对象提供的信息足够用于处理Web表单,但有些任务很单调,而且需要重复操作。

    indexhtml

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <style>
    .div1 {
        height: 180px;
        width: 380px;
        border: 1px solid #8A8989;
        margin: 0 auto;
    }
    .input {
        display: block;
        width: 350px;
        height: 40px;
        margin: 10px auto;
    }
    .button {
        background: #2066C5;
        color: white;
        font-size: 18px;
        font-weight: bold;
        height: 50px;
        border-radius: 4px;
    }
    </style>
    <div class="div1">
    {#  action:接受的路由  #}
        <form action="/login" method="post">
            <input type="text" class="input" name="username" placeholder="请输入用户名">
            <input type="password" class="input" name="pwd" placeholder="请输入密码">
            <input type="submit" value="登录" class="input button">
        </form>
    </div>
    </body>
    </html>
    

    app.py

    # @time:2020/11/8 16:18
    # Author:Small-J
    
    from flask import Flask, render_template, request
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def hello_world():
        return render_template('index5.html')
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            return '这是get请求'
        else:
            return '这是post请求'
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    发送post请求成功

    Flask框架之数据交互的实现

    使用Postman发送Get请求成功

    Flask框架之数据交互的实现

    在上面的工程中,对表单没有进行必要的保护措施,很容易被人利用,控制用户在当前已登录的Web应用程序上执行非本意的操作。因此,在实际部署服务器上的代码时,不建议使用这个方式处理表单,推荐使用Flask-WTF方式进行表单处理。

    1.2 使用Flask-WTF处理表单

    Flask-WTF的安装:pip install flask-wtf

    启动CSRF保护

    Flask-WTF提供了对所有Form表单免受跨站请求伪造(Cross-Site Request Forgery, CSRF)攻击的技术支持(通过添加动态token令牌的方式)

    我们在Flask根目录下新增config.py配置文件,要启动CSRF保护,可以在config.py中定义两个变量

    # @time:2020/11/8 16:54
    # Author:Small-J
    import os
    import random
    
    # 开启CSRF保护
    CSRF_ENABLED = True
    
    # 生成密钥
    SECRET_KEY = os.urandom(24)
    

    form.py

    # @time:2020/11/8 17:00
    # Author:Small-J
    
    # 引入Form元素的基类
    from flask_wtf import Form
    # 引入Form元素的父类
    from wtforms import StringField, PasswordField
    # 引入Form验证父类
    from wtforms.validators import DataRequired, Length
    
    
    # 登录表单类,继承于Form类
    class BaseLogin(Form):
        # 用户名
        name = StringField('name', validators=[DataRequired(message="用户名不能为空"), Length(6, 16, message="长度为6~16之间")], render_kw={'placeholder': '输入用户名'})
    
        # 密码
        password = PasswordField('password', validators=[DataRequired(message="密码不能为空"), Length(6, 16, message='长度位于6~16之间')], render_kw={'placeholder': '输入密码'})
    
    

    app.py

    # @time:2020/11/8 16:54
    # Author:Small-J
    
    from flask import Flask, flash
    from flask import url_for, render_template
    from flask_wtf.csrf import CSRFProtect
    
    # 导入定义的BaseLogin
    from forms import BaseLogin
    import config
    
    app = Flask(__name__)
    # 配置文件初始化
    app.config.from_object(config)
    
    
    @app.route('/login', methods=['POST', 'GET'])
    def base_login():
        form = BaseLogin()
        # 判断验证提交是否通过
        if form.validate_on_submit():
            flash(form.name.data + '|' + form.password.data)
            return '表单数据提交成功'
        else:
            return render_template('login.html', form=form)
    
    
    @app.route('/')
    def hello_world():
        return 'Hello World'
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Flask_WTF</title>
    </head>
    <body>
    <style type="text/css">
        .div1 {
            height: 180px;
            width: 380px;
            border: 1px solid #8A8989;
            margin: 0 auto;
        }
        .input {
            display: block;
            width: 350px;
            height: 40px;
            margin: 10px auto;
        }
        .button {
            background: #2066C5;
            color: white;
            font-size: 18px;
            font-weight: bold;
            height: 50px;
            border-radius: 4px;
        }
    </style>
    <div class="div1">
        <form action="/login" method="post">
            <!--启动CSRF-->
            {{ form.hidden_tag() }}
            {{ form.name(size=16, id='name', class='input') }}
                {% for e in form.name.errors %}
                    <span style="color: red">{{ e }}</span>
                {% endfor %}
            {{ form.password(size=16, id='password', class='input') }}
                {% for e in form.password.errors %}
                    <span style="color: red">{{ e }}</span>
                {% endfor %}
            <input type="submit" value="登录" class="input button">
        </form>
    </div>
    </body>
    </html>
    

    2 使用Flask上传文件

    在Web开发时,经常需要实现文件上传功能。可以以普通方式进行文件的上传,上传过程一般要检查上传的文件格式是否符合要求,文件保存时注意绝对路径和相对路径。

    Flask文件上传比较简单,需要注意以下3点要求:

    • 一个标签被标记有enctype=multipart/form-data,并且在里面包含一个input type=file
    • 服务器端应用通过请求对象上的files字典访问文件。
    • 使用文件的save()方法将文件永久地保存在文件系统上的某处。
    • 注意:表单中必须要求enctype=“multipart/form-data”,否则上传文件无效。一般可以写成<form action="" method=“post” enctype=“multipart/form-data”

    import osfrom os import path指的是导入os模块及os模块下的path方法。方法下相关属性如下:

    • os.path.sep : windows下路径分隔符是反斜杠\;
    • os.path.altsep : linux下路径分隔符是/根目录:
    • os.path.curdir当前目录 :
    • os.path.pardir父目录 : os.path.abspath(path)
    • 绝对路径: os.path.join()

    注意:什么是文件分隔符?将表格转换为文本时,用分隔符标识文件分隔的位置或将文本转换成表格时,用其标识新行或新列的起始位置。不同操作系统下文件分隔符是不同的,Windows中是"", Linux中是"/"

    # @time:2020/11/8 21:48
    # Author:Small-J
    
    # 导入secure_filename方法,将中文文件名传给secure_filename
    from werkzeug.utils import secure_filename
    from flask import Flask, render_template, request
    import os
    from os import path
    
    app = Flask(__name__)
    
    
    # 指定该路由可以使用的请求方式,get和post请求两种方式
    @app.route('/', methods=['POST', 'GET'])
    def hello_world():
        # method : 请求的方法
        if request.method == 'GET':
            return render_template('upload.html')
        else:
            # request.files:代表着获取文件流
            # 这里接受的file指的是对应name对应的值
            f = request.files['file']
            # 去掉其中文命名
            filename = secure_filename(f.filename)
            # save : 字节保存语句拼接
            f.save(path.join('static/uploads', filename))
            return "上传文件成功!"
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
        <style type="text/css">
        .div1 {
            height: 180px;
            width: 380px;
            border: 1px solid #8A8989;
            margin: 0 auto;
        }
        .input {
            display: block;
            width: 250px;
            height: 30px;
            margin: 10px auto;
        }
        .button {
            background: #2066C5;
            color: white;
            font-size: 18px;
            font-weight: bold;
            height: 30px;
            border-radius: 4px;
    
        }
    </style>
    </head>
    <body>
    <div class="div1">
    {# 当选择文件上传的时候,我们需要使用到enctype,否则是无法上传使用的   #}
    {#  multipart/form-data:在使用包含文件上传控件的表单时,必须使用该值  #}
        <form action="" method="post" enctype="multipart/form-data">
            <input type="file" name="file" class="input">
            <input type="submit" value="上传" class="input button">
        </form>
    </div>
    </body>
    </html>
    

    上传文件

    Flask框架之数据交互的实现

    3 Cookie的使用

    Cookie有时也记作Cookies,它现在经常被大家提到,那么到底什么是Cookies?它有什么作用呢?Cookies是一种能够让服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。当你再次浏览某网站时,浏览器将存放于本地的用户身份信息递交给服务器,服务器就可以识别用户的身份

    3.1 Cookie的基本概念

    当用户访问服务器并登录成功后,服务器向客户端返回的一些数据(Cookie),客户端将服务器返回的Cookie数据保存在本地,当用户再次访问服务器时,浏览器自动携带Cookie数据给服务器,服务器便自动访问者的身份信息。

    Cookie基本的语法:set_cookie(name, value, expire, path, domain, secure)

    参数 描述
    name 必需项,规定Cookie的名称
    value 必需项,规定Cookie的值
    expire 可选项,规定Cookie的有效期
    path 可选项,规定Cookie在当前Web下哪些目录有效
    domain 可选项,规定Cookie作用的有效域名
    secure 可选项,规定是否通过安全的HTTPS连接来传输Cookie

    3.2 Cookie的基本使用

    我们在Flask中自定义Cookie,实际上就是在相应Response的Set-Cookie字段中新增加自定义的键值对。而获取Cookie,就是在请求Request中通过键获取对应的值,所以,在工程中必须引入Request和Response模块。

    设置Cookie

    设置Cookie主要有两种方法,一种是通过Response对象设置,另一种是通过直接设置表单头来实现。

    # @time:2020/11/9 13:20
    # Author:Small-J
    
    from flask import Flask, request, Response
    
    app = Flask(__name__)
    
    
    @app.route('/')
    def set_cookie():
        # 创建响应
        resp = Response("设置Cookie!")
        # 设置Cookie名称
        resp.set_cookie('username', 'Small-J')
        return resp
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    Flask框架之数据交互的实现

    Flask框架之数据交互的实现

    查看Cookie

    查看已经设置好的Cookie,可以通过request.cookies.get来得到

    @app.route('/get_cookie')
    def get_cookie():
        # 可通过请求cookies方式来获取
        username = request.cookies.get('username')
        return username
    

    删除Cookie

    删除已经设置好的Cookie,可以通过delete_cookie()来完成。delect_cookie括号中对象为被删除的对象名,比如delect_cookie("username")

    @app.route('/del_cookie')
    def del_cookie():
        # 创建响应
        resp = Response('删除Cookie')
        # 删除Cookie
        resp.delete_cookie("username")
        return resp
    
    

    4 Session的使用

    Session是基于Cookie实现的,保存在服务器的键值对(session[‘name’] = ‘value’)中。同时,在浏览器的Cookie也对应一个相同的随机字符串,用来再次请求的时验证

    注意:Session是存储在服务器中的,Cookies是储存在浏览器本地中,而Flask的Session是基于Cookies,Session是经过加密保存在Cookies中。

    4.1 Session的基本配置

    因为Flask的Session是通过加密之后放在了Cookie中。有加密就有密钥用于解密,所以,用到了Flask的Sessio模块就一定要配置SECRET_KEY这个全局宏。一般将SECRET_KEY设置为24位的字符。我们可以自己设定一个随机字符串,例如:

    app.config['SECRET_KEY'] = XXXXXXX

    我们也可以引入OS模块中,自动产生一个24位的随机字符串函数。这种方法有个不足之处,就是服务器每次启动之后这个SECRET_KEY的值是不一样的,会造成Session验证失效,用户只有重新登录。

    4.2 Session的基本使用

    设置Session

    设置Session主要是通过session['name'] = 'value'方法来完成,name代表的是变量名称,value代表的是变量的值

    # @time:2020/11/9 16:59
    # Author:Small-J
    
    from flask import Flask, session
    import os
    
    app = Flask(__name__)
    # 产生SECRET_KEY值
    app.config['SECRET_KEY'] = os.urandom(24)
    
    
    @app.route('/')
    def set_session():
        session['username'] = 'Small-J'
        return 'Session设置成功'
    
    

    Flask框架之数据交互的实现

    获取Session的值

    获取Session的值有两种方法

    • session['name']: 如果内容不存在,将会报异常
    • session.get('name') : 如果内容不存在,将会返回None
    class GetSession(views.View):
        """获取session的值"""
        def dispatch_request(self):
            username = session.get('username')
            return username or "Session为空"
    
    
    # 添加路由规则
    app.add_url_rule(rule='/get_session', endpoint='get_session', view_func=GetSession.as_view('session'))
    

    删除Session的值或清空Session所有值

    删除单个Session的值,可以使用Session.pop('key')这个方法,如果清除多个Session的值,可以使用Session.clear方法

    class DelSession(views.View):
        """删除session的值"""
        def dispatch_request(self):
            # 删除单个session
            session.pop('username')
            # 清空
            # session.clear()
            return 'Session被删除'
    

    Flask框架之数据交互的实现

    设置Session的过期时间

    如果没有指定Session的过期时间,那么默认就是浏览器关闭后自动结束,即关闭浏览器失效。session.permanent=True在Flask下则可以将有效期延长至一个月。下面的方法可以配置具体多少天的有效期。

    如果设置了Session的permanent属性为True,那么过期时间是31天。

    可以通过给app.config设置PERMANENT_SESSION_LIFETIME来更改过期时间

    在实际项目开发中可能还有一种需求,就是指定Session的失效时间为3天、7天、10天等整数天数的情况,这里主要用到了一个持续久化的会话生成的时间(实质就是Session会话的有效期)PERMANENT_SESSION_LIFETIME,作为一个datetime.timedelta对象

    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。