• 01-flask创建/路由/http请求与相应


    一、关于Flask

    Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。

    与django做对比:

    如果做一个小型项目用django做是比较笨重的,django下载加上其他的一些包,运行速度其实是不快的,一个小型项目有很多包是用不上的

    为了保证我们实现的功能是高定制性的,很多公司都采用flask

    牛逼点的公司直接用flask做些大项目,性能肯定比django要好

    Flask就是一个核心类而已,核心类只提供了3-4个包给我们,其他所有的包按需安装

    其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是 Flask 框架的核心。

    Flask常用第三方扩展包:

    • Flask-SQLalchemy:操作数据库,ORM;

    • Flask-script:终端脚本工具,脚手架;

      • 这一系列终端脚本工具用一个名词来表达它,脚手架
      • 把自己编好的一些工具,通过简单命令就可以生成一个目录或数据或文件的这种工具称脚手架工具
    • Flask-migrate:管理迁移数据库;

    • Flask-Session:Session存储方式指定;

      • 可以把Session转移他的存储方式,在以前默认是存储在文件中,后面存到了mysql数据库里面,存到redis的话,需要安装
    • Flask-WTF:表单;

      • django中可以通过Model From自动生成表达,
    • Flask-Mail:邮件;

    • Flask-Bable:提供国际化和本地化支持,翻译;

    • Flask-Login:认证用户状态;

    • Flask-OpenID:认证, OAuth;

    • Flask-RESTful:开发REST API的工具;

    • Flask JSON-RPC: 开发rpc远程服务[过程]调用

    • Flask-Bootstrap:集成前端Twitter Bootstrap框架

      • 安装admiin如果要切换一个主题,要安装Bootstrap
    • Flask-Moment:本地化日期和时间

      • 用到日期时间的转换,需要安装
    • Flask-Admin:简单而可扩展的管理接口的框架

    二、简单应用flask

    创建虚拟环境

    mkvirtualenv flask -p python3

    安装flask

    pip install flask==0.12.5

    安装完只提供这几个模块

    • Jinja2-2.11.2:模板引擎
    • MarkupSafe-1.1.1:编码转换工具 主要针对html里面的大于号小于号转换为& lt
    • Werkzeug-0.16.1:路由模块
    • click-7.1.2:时间监听系统
    • flask-0.12.5:flask本身内核,flask本身写的那个类
    • itsdangerous-1.1.0:数据加密传输
    pip freeze

    新建一个文件夹 flask_demo

    新建一个文件main.py

    from flask import Flask
    
    # 创建应用对象
    app = Flask(__name__)
    
    # 视图加载
    @app.route(rule="/") # 声明路由
    def index():    # 声明视图函数
        return "<h1>python31</h1>"  # 直接通过return返回普通字符串
    
    if __name__ == '__main__':
        # 启动项目,不要在run 后面写任何代码,不会被执行到
        app.run(debug=True, port=8000,host="0.0.0.0") #wsgiref模块提供的

    首先在flask包里有一个全局对象,充当一个应用,

    每一个网站只有一个唯一的app,通过flask创建,创建时需要拿到我们的这个文件,所以就把__name__传进去

    app提供了flask所有要用的东西,其中有一个route,是设置路由的

    装饰视图函数

    app.run(),启动了我们的测试服务器,由wsgiref模块提供的

    有两个参数

    debug=True 默认是不会重启的,因为默认debug=False,为True就启动了debug模式

    port=8000 绑定了8000端口

    host="0.0.0.0" 任意客户端都能访问

    1、Flask() 参数

        def __init__(self, import_name, static_path=None, static_url_path=None,
                     static_folder='static', template_folder='templates',
                     instance_path=None, instance_relative_config=False,
                     root_path=None):
    """
    import_name      Flask程序所在的包(模块),传 __name__ 就可以
                     其可以决定 Flask 在访问静态文件时查找的路径
    static_path      静态文件访问路径(不推荐使用,使用 static_url_path 代替)
    static_url_path  静态文件访问路径,可以不传,默认为:/ + static_folder
    static_folder    静态文件存储的文件夹,可以不传,默认为 static
    template_folder  模板文件存储的文件夹,可以不传,默认为 templates
    """

    三、加载配置

    from flask import Flask
    
    # 1. 实例化flask 应用对象
    app = Flask(__name__)
    
    # 1.1 配置信息
    class Config():
        # 配置项目运行在debug调试模式下
        DEBUG = True
    
    # 1.1 加载配置到应用对象中
    app.config.from_object(Config)
    
    # 2. 编写视图和路由
    @app.route(rule="/", methods=["get"])
    def index():
        return "<h1>hello flask</h1>"
    
    if __name__ == '__main__':
        app.run()

    加载配置到应用对象,加载有五种方式

    • app.config.from_envvar: 表示从环境变量里提取我们要的数据
    • app.config.from_json: 从json文件中读取
    • app.config.from_mapping: 一种映射关系,类似于字典的键值对
    • app.config.from_object: 通过对象
    • app.config.from_pyfile: 通过模块

    四、路由的基本使用、自定义路由转换器

    路由和视图的名称必须全局唯一,不能出现重复,否则报错。

    什么是路由:

    一种访问地址[url]和应用程序[视图]进行一对一绑定的映射关系

    在开发中,我们所说的路由,其实通常指代完成路由绑定关系订单路由类

    url中可以传递路由参数, 2种方式

    1、任意路由参数接收

    from flask import Flask
    
    # 1. 实例化flask 应用对象
    app = Flask(__name__)
    
    # 1.1 配置信息
    class Config():
        # 配置项目运行在debug调试模式下
        DEBUG = True
    
    # 1.1 加载配置到应用对象中
    app.config.from_object(Config)
    
    # 2. 编写视图和路由
    @app.route(rule="/", methods=["get"])
    def index():
        return "<h1>hello flask</h1>"
    
    @app.route(rule="/user/<user_id>") # 没有限定参数的类型,所以user_id可以是数字,也可以是其他类型的信息
    def user(user_id):
        print(user_id)
        return "<h1>hello user</h1>"
    
    
    if __name__ == '__main__':
        app.run()

     视图函数的参数名称必须与路由上面的保持一致,否则接收不了

    1.1、限定路由参数的数据类型

    通过路由转换器限定路由参数的类型,flask系统自带转换器编写在werkzeug.routing.py文件中。底部可以看到以下字典:

    DEFAULT_CONVERTERS = {
       "default": UnicodeConverter,
       "string": UnicodeConverter,
       "any": AnyConverter,
       "path": PathConverter,
       "int": IntegerConverter,
       "float": FloatConverter,
       "uuid": UUIDConverter,
    }

    默认路由转换器,是一个字典

    系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

    转换器名称描述
    string 默认类型,接受不带斜杠的任何文本
    int 接受正整数
    float 接受正浮点值
    path 接收string但也接受斜线
    uuid 接受UUID(通用唯一识别码)字符串 xxxx-xxxx-xxxxx-xxxxx
    from flask import Flask
    
    # 创建应用对象
    app = Flask(__name__)
    
    # 加载配置
    class Config():
        DEBUG = True
    
    app.config.from_object(Config)
    
    # 路由转换器对路由参数的类型进行限定
    @app.route(rule="/<float:user_id>")
    def index(user_id):
        print(type(user_id))  # <class 'float'>
        return "user_id=%s" % user_id
    
    
    if __name__ == '__main__':
        app.run()

    默认路由转换器不能满足我们的具体业务,比如希望接收一个字符串,但是这个字符串必须数字组成,有时候还要限定是手机格式,邮箱格式等,通过上面的七个是解决不了的

    1.2、自定义路由转换器

    参考默认的模式写自定义路由转换器

    必须直接或间接继承BaseConverter,提供了识别路由的方案

    定义规则

    map 就是 url_map

    类似django里面的urlpatterns app.url_map 每个成员就是一个类

    然后把我们自己写的类映射进去

    from flask import Flask
    
    # 实例化flask 应用对象
    app = Flask(__name__)
    
    # 自定义路由参数转换器
    # 1. 引入BaseConverter路由参数转换器基类
    from werkzeug.routing import BaseConverter
    
    # 2. 自定义路由参数转换器
    class MobileConverter(BaseConverter):
        regex = r"1[3-9]d{9}"
        def __init__(self,map,*args,**kwargs):
            super().__init__(map,*args,**kwargs)
    
    # 3. 注册路由参数转换到app应用对象中
    app.url_map.converters["mobile"] = MobileConverter
    
    # 编写视图和路由
    @app.route(rule="/user/<mobile:user_mobile>")
    def user(user_mobile):
        print(user_mobile)
        return "<h1>hello user</h1>"
    
    # url_map是flask路由列表对象,类似之前在django里面的urlpatterns
    
    if __name__ == '__main__':
        app.run(debug=True)

    这样写有个不好的点就是,写了一个正则限定的类,将来如果有更多的格式要求,那每一个都要写一个路由转换器,这样就特别麻烦

    直接在路由里面写正则参数

    1.3、基于路由参数转换器实现类似django的re_path效果接收正则限定参数

    from flask import Flask
    
    # 实例化flask 应用对象
    app = Flask(__name__)
    
    # 基于自定义路由参数转换器实现类似django的re_path这样的正则路由参数
    # 1. 引入BaseConverter路由参数转换器基类
    from werkzeug.routing import BaseConverter
    
    # 2. 自定义路由参数转换器
    class RegexConverter(BaseConverter):
        def __init__(self,map,*args):
            super().__init__(map)
            self.regex = args[0]
    
    # 3. 注册路由参数转换到app应用对象中
    app.url_map.converters["re"] = RegexConverter
    
    # 编写视图和路由
    @app.route(rule="/user/<re('d{6}'):mobile>")
    def user(mobile):
        print(mobile)
        return "<h1>hello user</h1>"
    
    # url_map是flask路由列表对象,类似之前在django里面的urlpatterns
    
    if __name__ == '__main__':
        app.run(debug=True)

     2、指定请求方式

    from flask import Flask
    
    app = Flask(__name__)
    
    # 路由转换器对路由参数的类型进行限定
    @app.route(rule="/",methods=["POST","PUT","PATCH","DELETE"])
    # @app.route(rule="/") # 没有填写第二个参数methods则默认只能通过get请求访问
    def index():
        return "ok"
    
    if __name__ == '__main__':
        app.run(debug=True)

    五、路由与视图分离

    from flask import Flask
    app = Flask(__name__)
    
    def index():
        return 'Hello World'
    
    # 也可以让路由注册和视图进行分离
    app.add_url_rule(rule="/", view_func=index)
    
    if __name__ == '__main__':
        app.run()

    六、http请求和相应

    1、http请求

    声明request对象

    from flask import request

    request就可以帮我们获取客户端里的数据,包括路径上的字符串、请求头、请求体等等信息

    文档: http://docs.jinkan.org/docs/flask/api.html#flask.request

    • request:flask中代表当前请求的 request 对象

    • 作用:在视图函数中取出本次请求数据

    • 导入from flask import request

    • 代码位置:from flask.app import Request

    常用的属性如下:

    属性说明类型
    data 记录请求体的数据,并转换为字符串 只要是通过其他属性无法识别转换的请求体数据 最终都是保留到data属性中 bytes类型
    form 记录请求中的html表单数据 MultiDict
    args 记录请求中的查询字符串,也可以是query_string MultiDict
    cookies 记录请求中的cookie信息 Dict
    headers 记录请求中的请求头 EnvironHeaders
    method 记录请求使用的HTTP方法 GET/POST
    url 记录请求的URL地址 string
    files 记录请求上传的文件列表 *
    json 记录ajax请求的json数据 json

    获取提交请求的html表单数据

    from flask import Flask,request
    from werkzeug.datastructures import ImmutableMultiDict
    
    app = Flask(__name__)
    
    @app.route("/form",methods=["POST","PUT","PATCH"])
    def get_form():
        print(request) # HTTP请求处理对象
        # 接受表单数据
        print(request.form)
        """打印效果:
        ImmutableMultiDict([('username', 'xiaoming'), ('password', '123456'), ('lve', 'swimming'), ('lve', 'game'), ('lve', 'shopping')])
        # ImmutableMultiDict 这个类就是一个字典的子类,我们可以称之为类字典对象,所以可以通过字典的操作来使用。
        # 思路来源: from collection import OrderedDict
        """
        # 获取指定键的单个值
        print(request.form.get("username"))
        print(request.form["username"])
        print(request.form["lve"]) # 如果键对应的数据有多个值,则不能通过get或中括号
    
        # 获取指定键获取多个值
        print(request.form.getlist("lve")) # ['swimming', 'game', 'shopping']
    
        # 格式转换
        # ImmutableMultiDict 转换成基本格式
        # 注意: 转换过程中,如果出现一个键对应多个值的情况,则取第一个值
        ret = request.form.to_dict() # {'username': 'xiaoming', 'password': '123456', 'lve': 'swimming'}
        
        return "ok"
    
    if __name__ == '__main__':
        app.run(debug=True)

    获取query_params

    查询字符串,不限任何的请求类型,通过地址+? 127.0.0.1:8000?aa=1

    获取请求头

    from flask import Flask,request
    from werkzeug.datastructures import ImmutableMultiDict
    
    app = Flask(__name__)
    
    @app.route("/query")
    def get_query_params():
        """获取查询字符串 query_params"""
        print(request.args)
        """打印效果:
        ImmutableMultiDict([('username', 'xiaoming'), ('age', '18')])
        """
        print(request.args.to_dict()) # {'username': 'xiaoming', 'age': '18'}
        return "ok"
    
    @app.route("/head")
    def get_head():
        """获取请求头数据"""
        print(request.headers)
        print(request.headers["Content-Type"]) # application/x-www-form-urlencoded
    
        # 获取自定义请求头[首字母大写,不支持多个单词使用横杠进行拼接的写法,也不支持多字节字符]
        print(request.headers["Company"]) # oldboyedu
        return "ok"
    
    @app.route("/",methods=["POST","GET"])
    def index():
        print(request.method) # GET 获取本次客户端的请求方法名
        print(request.url) # http://127.0.0.1:5000/  url地址
        print(request.json) # {'pay_type': 1, 'credit': 0, 'coupon': 0} 获取json数据
    
        print(request.files) # ImmutableMultiDict([('video1', <FileStorage: 'demo.mp4' ('video/mp4')>)])
        print(request.files.get("video1"))
        return "ok"
    
    if __name__ == '__main__':
        app.run(debug=True)

    获取请求数据所有

    from flask import Flask
    
    # 实例化flask 应用对象
    app = Flask(__name__)
    
    # 编写视图和路由
    from flask import request
    from urllib.parse import parse_qs
    @app.route(rule="/user", methods=["get","post","put","patch","delete"])
    def user():
        # print(request.method) # 获取本次客户端的http请求方法         GET
        # print(request.path)  # 获取本次客户端请求的路由路径部分[去掉域名端口]    /user
        # print(request.url) # 获取本次客户端请求的http url地址        http://127.0.0.1:5000/user?user=1
    
        # 获取查询字符串
        # print(request.query_string)  # 获取本次客户端的(原始)查询字符串    b'user=1'
        # query_string = parse_qs(request.query_string)
        # print(query_string)  # {b'lve': [b'swimming', b'pingpang']}
        # print(query_string["lve".encode()][0].decode())
        # print(request.args)          # 获取本次客户端的(Dict字典)查询字符串  from collections import OrderedDict
        # print(request.args.get("lve"))  # 提取一个值
        # print(request.args.getlist("lve")) # 提取多个值
        print(request.args.to_dict())  # {'lve': 'swimming'}
        """
        ImmutableMultiDict的实例对象 提供了四个常用的方法给我们获取数据,
        1. get 获取指定参数的第一个值
        2. getlist 获取指定参数的多个值
        3. to_dict 把所有参数转换成字典[request对象的部分属性不支持]
        4. to_list 把所有参数转换成列表[request对象的部分属性不支持]
        """
        # 获取html表单,视图必须支持post方法访问
        # print(request.form)    # 表单中的全部数据
        # print(request.form.get("username")) # 表单单个数据
        # # 获取ajax或者表单中的上传文件都需要使用request.files
        # print(request.files.get("avatar"))  # <FileStorage: '2.jpg' ('image/jpeg')>
    
        # 获取json数据
        # print(request.json)  # {'username': 'xiaohuihui'}
    
        # 获取请求头
        # print(request.headers) #
        print(request.headers.to_list()) # 获取请求头
        # print(request.headers.get("Host")) # 获取请求头,REMOTE_ADDR客户端的地址
        print(request.headers.get("Company")) # 获取自定义请求头,首字母大写
    
        # 其他属性
        print(request.is_json) # 是否是ajax请求
        
        return "<h1>hello user</h1>"
    
    if __name__ == '__main__':
        app.run(debug=True)

    2、响应

    from flask import Flask,request,make_response,Response,jsonify
    
    app = Flask(__name__)
    
    @app.route("/")
    def index():
        """返回html数据"""
    
        # return "ok"
        # return make_response("ok") # 上面的代码是这段代码的简写
        # return Response("ok") # 上面make_response本质上就是Response
    
        """返回json格式数据"""
        # data = {"name":"xiaoming","age":13}
        # return jsonify(data)
    
        """返回其他类型数据"""
        # 关于Response常用的参数
        # Response(response="内容", status="http响应状态码",headers=自定义响应头,mimetype="数据格式")
        # return Response(response="ok",status=201,headers={"company":"hello"})
        # 返回图片信息
        with open('./1.zip',"rb") as f:
            content=f.read()
        # 判断权限,身份...
        return Response(response=content,mimetype="application/zip")
    
    if __name__ == '__main__':
        app.run(debug=True)

    make_response:

    调用视图,判断视图执行的返回值是不是reponse的一个实例对象,如果不是就把内容再实例化一遍

    3、重定向

    from flask import Flask,redirect,url_for
    app = Flask(__name__)
    
    @app.route("/index")
    def index():
        return 'index'
    
    # 站内跳转,进行视图之间的跳转
    @app.route("/")
    def home():
        # 视图之间的跳转,可以携带get参数
        return redirect(url_for("index",name="xiaoming"))
    
    # 跳转到站外地址
    @app.route("/go")
    def go():
        return redirect("http://www.baidu.com")
    # 路由传递参数
    @app.route('/user/<user_id>')
    def user_info(user_id):
        return 'hello %d' % user_id
    
    # 重定向
    @app.route('/demo4')
    def demo4():
        # 使用 url_for 生成指定视图函数所对应的 url
        return redirect( url_for(endpoint="user",user_id=100) )

    4、自定义状态码和响应头

    在 Flask 中,可以很方便的返回自定义状态码,以实现不符合 http 协议的状态码,例如:status code: 666

    @app.route('/demo4')
    def demo4():
        return '状态码为 666', 400
      
    """还可以使用make_response创建Response对象,然后通过response对象返回数据"""
    from flask import make_response
    @app.route("/rep")
    def index7():
        response = make_response("ok")
        print(response)
        response.headers["Company"] = "oldboy" # 自定义响应头
        response.status_code = 201 # 自定义响应状态码
        return response

    七、http的会话控制

    http无状态的有所请求必有所回应的文件传输协议

    来自客户端的两次请求服务器不知道这两次请求到底是不是同一个客户端发送的

    """
    要有一个技术就是说用户在我们服务器活动的过程中,我们要跟踪他的一个行为记录,
    让它在客户端与服务端之间交互的过程中跟踪用户每一次的行为记录,和它的操作历史,这个就是会话跟踪技术.也称为会话控制技术
    """

    所谓的会话,就是客户端浏览器和服务端网站之间一次完整的交互过程.

    会话的开始是在用户通过浏览器第一次访问服务端网站开始. 也就是输入一个网站回车的一瞬间就开始了

    会话的结束时在用户通过关闭浏览器以后,与服务端断开.

    所谓的会话控制,就是在客户端浏览器和服务端网站之间,进行多次http请求响应之间,记录、跟踪和识别用户的信息而已。

     

    因为 http 是一种无状态协议,浏览器请求服务器是无状态的。

    无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。

    无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象。

    有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等

    实现状态保持主要有两种方式:

    • 在客户端存储信息使用 url地址, Cookie,token[jwt,csrf,oauth]

    • 在服务器端存储信息使用Session

    1、Cookie

    Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie的key/value可以由服务器端自己定义。

    使用场景: 登录状态, 浏览历史, 网站足迹,购物车 [不登录也可以使用购物车]

     

    Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用

    Cookie基于域名安全,不同域名的Cookie是不能互相访问的

    如访问ly.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到ly.com写的Cookie信息

    浏览器的同源策略针对cookie也有限制作用.

    当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息

     

    设置cookie

    设置cookie需要通过flask的Response响应对象来进行设置,由响应对象会提供了方法set_cookie给我们可以快速设置cookie信息。

    from flask imoprt Flask,make_response
    @app.route('/set_cookie')
    def set_cookie():
        resp = make_response('this is to set cookie')
        # response.set_cookie(key="变量名",value="变量值",max_age="有效时间/秒")
        resp.set_cookie('username', 'xiaoming', max_age=3600)
        """如果cookie没有设置过期时间,则默认过期为会话结束过期"""
        """cookie在客户端中保存时,用一个站点下同变量名的cookie会覆盖"""
        resp.set_cookie("age","100")
        return resp

    获取cookie

    from flask import Flask,request
    @app.route('/get_cookie')
    def resp_cookie():
        print(request.cookies)
        resp = request.cookies.get('username')
        print(request.cookies.get("age"))
        """打印效果:
        {'username': 'xiaoming'}
        """
        return resp

    删除cookie

    from flask import Flask,request
    @app.route("/del_cookie")
    def del_cookie():
        """删除cookie"""
        response = make_response("ok")
        #把对应名称的cookie设置为过期时间,则可以达到删除cookie
        response.set_cookie("username","",0)
        return response
    
    if __name__ == '__main__':
        app.run(debug=True)
        return resp

    Session

     

    from flask import Flask, make_response, request,session
    
    app = Flask(__name__)
    
    class Config():
        SECRET_KEY = "123456asdadad"
        DEBUG = True
    
    app.config.from_object(Config)
    
    # 查看当前flask默认支持的所有配置项
    # print(app.config)
    """
    <Config {
     'DEBUG': False,
     'TESTING': False,
     'PROPAGATE_EXCEPTIONS': None,
     'PRESERVE_CONTEXT_ON_EXCEPTION': None,
     'SECRET_KEY': None,                   # 秘钥
     'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), # 文件有效期
     'USE_X_SENDFILE': False,
     'LOGGER_NAME': '__main__',
     'LOGGER_HANDLER_POLICY': 'always',
     'SERVER_NAME': None,
     'APPLICATION_ROOT': None,
     'SESSION_COOKIE_NAME': 'session',     # 名称
     'SESSION_COOKIE_DOMAIN': None,
     'SESSION_COOKIE_PATH': None,          # 路径
     'SESSION_COOKIE_HTTPONLY': True,
     'SESSION_COOKIE_SECURE': False,       # 加密
     'SESSION_REFRESH_EACH_REQUEST': True, # 刷新
     'MAX_CONTENT_LENGTH': None,
     'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200),
     'TRAP_BAD_REQUEST_ERRORS': False,
     'TRAP_HTTP_EXCEPTIONS': False,
     'EXPLAIN_TEMPLATE_LOADING': False,
     'PREFERRED_URL_SCHEME': 'http',
     'JSON_AS_ASCII': True,
     'JSON_SORT_KEYS': True,
     'JSONIFY_PRETTYPRINT_REGULAR': True,
     'JSONIFY_MIMETYPE': 'application/json',
     'TEMPLATES_AUTO_RELOAD': None
    """

    session相关配置项文档:

    https://dormousehole.readthedocs.io/en/latest/config.html?highlight=session_cookie_path

    对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息

    在服务器端进行状态保持的方案就是Session

    Session依赖于Cookie,session的ID一般默认通过cookie来保存到客户端。

    flask中的session需要加密,所以使用session之前必须配置SECRET_KEY选项,否则报错.

    session的有效期默认是会话期,会话结束了,session就废弃了。

    如果将来希望session的生命周期延长,可以通过修改cookie中的sessionID来完成配置。

    设置session

    from flask import session
    @app.route('/set_session')
    def set_session():
        session['username'] = 'xiaoming'
        return 'ok!'

    获取session

    from flask import session
    @app.route('/get_session')
    def get_session():
        return session.get('username')

     总体加了一个SECKET_KEY

    from flask import Flask, make_response, request,session
    
    app = Flask(__name__)
    
    class Config():
        SECRET_KEY = "123456asdadad"
        DEBUG = True
    
    app.config.from_object(Config)
    
    # 查看当前flask默认支持的所有配置项
    # print(app.config)
    """
    <Config {
     'DEBUG': False,
     'TESTING': False,
     'PROPAGATE_EXCEPTIONS': None,
     'PRESERVE_CONTEXT_ON_EXCEPTION': None,
     'SECRET_KEY': None,
     'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31),
     'USE_X_SENDFILE': False,
     'LOGGER_NAME': '__main__',
     'LOGGER_HANDLER_POLICY': 'always',
     'SERVER_NAME': None,
     'APPLICATION_ROOT': None,
     'SESSION_COOKIE_NAME': 'session',
     'SESSION_COOKIE_DOMAIN': None,
     'SESSION_COOKIE_PATH': None,
     'SESSION_COOKIE_HTTPONLY': True,
     'SESSION_COOKIE_SECURE': False,
     'SESSION_REFRESH_EACH_REQUEST': True,
     'MAX_CONTENT_LENGTH': None,
     'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200),
     'TRAP_BAD_REQUEST_ERRORS': False,
     'TRAP_HTTP_EXCEPTIONS': False,
     'EXPLAIN_TEMPLATE_LOADING': False,
     'PREFERRED_URL_SCHEME': 'http',
     'JSON_AS_ASCII': True,
     'JSON_SORT_KEYS': True,
     'JSONIFY_PRETTYPRINT_REGULAR': True,
     'JSONIFY_MIMETYPE': 'application/json',
     'TEMPLATES_AUTO_RELOAD': None
    """
    @app.route("/set_session")
    def set_session():
        """设置session"""
        """与cookie不同,session支持python基本数据类型作为值"""
        session["username"] = "xiaohuihui"
        session["info"] = {
            "age":11,
            "sex":True,
        }
    
        return "ok"
    
    @app.route("/get_session")
    def get_session():
        """获取session"""
        print( session.get("username") )
        print( session.get("info") )
        print( app.session_cookie_name )
        return "ok"
    
    @app.route("/del_session")
    def del_session():
        """删除session"""
        try:
            del session["username"]
            # session.clear() # 删除所有
        except:
            pass
        return "ok"
    
    if __name__ == '__main__':
        app.run(debug=True)

     

     

  • 相关阅读:
    利用后退按钮进行重复提交的解决办法。
    运用上传拦截器时遇到的一个问题
    Fckeditor上传图片的错误
    关于分页的一些经验。
    spring在web工程中的运用
    引入js失败的可能原因
    hql执行update行为时可能遇到的一个问题。
    Eclipse下freemarker插件的安装
    同名文本框与同名复选框在传值上的不同.
    spring在java工程中的运用
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/14000970.html
Copyright © 2020-2023  润新知