美文网首页
flask-16day

flask-16day

作者: DayBreakL | 来源:发表于2022-11-09 00:40 被阅读0次

    Day1

    flask依赖包

    当执行pip install flask后,会发现多了这些依赖
    1.Flask flask核心库
    2.Jinja2 模板渲染库
    3.Markupsafe 安全标签库 只要flask返回模板或者标签时,都会依赖它
    4.Werkzeug 德文“工具”的意思,应用程序网关接口库 WSGI,flask项目启动基于Werkzeug

    启动项目实现hello world

    注意:尽量不要使用pycharm中自带的flask模板创建flask

    启动服务:

    from flask import Flask # 导入flask核心类,创建Flask应用对象
    app = Flask(__name__) # app-application,实例化的flask对象
    app.run() # 启动Flask
    

    实现helloworld

    from flask import Flask 
    app = Flask(__name__) 
    @app.route("/index"):   # 为flask应用对象增加路由
     def index(): # 与路由绑定的视图函数
         return "hello world" # 返回,相当于响应
    
    if __name__ == '__main__':
          app.run()
    

    response

    1.return "hello world"

    2.return render_template("xxx.html")
    html文件的默认存放路径是/templates

    3.return redirect("/home")

    重定向路由

    @app.route("/home")
    def home():
        return "home主页"
    
    
    @app.route("/red")
    def red():
        return redirect("/home")
    

    当访问/red时,http status 302,3xx表示当前浏览器要做出指令。
    请求时,response header中有参数location:http://127.0.0.1:5000/home,就会根据location对应的地址跳转。

    小知识:pycharm中redirect("/home")("/home")会有小黄块,提示的意思是,不知道这个/home存在或者不存在,所以可以把templates标记为templates folder,这样黄色的小块就不在了。

    image.png

    4.return send_file("文件路径")
    打开,并返回文件内容,并自动识别文件类型,在response header中加入,不能识别的类型,仅会做下载处理。(其实所有的都会下载,只是浏览器能够识别图片、map4,所以给你播放出来了。并且把Content-Type作为标签放到了页面上,识别文件类型的能力取决于浏览器,如wma文件,微软自带的录音文件格式,所以只有ie浏览器能识别,而其他浏览器不能识别)
    如:
    放一个jpg文件,response header中Content-Type: image/jpeg
    放一个mp4文件,response header中Content-Type: video/mp4
    Content-Type :文件类型

    二进制文件的第一行,会写文件类型,如果没有写文件类型,就是普通的文本文件。

    5.jsonify 返回标准格式

    @app.route("/get_json")
    def get_json():
        data = {"username": "tony"}
        return jsonify(data)
    

    Content-Type: application/json

    flask1.1.1以上版本,可以直接使用 return data,即return一个字典时,就是在执行jsonify,不建议使用,因为要兼容低版本。

    修改app.config['JSONIFY_MINETYPE'],就是修改jsonify解析时返回的response header中Content-Type

    request

    1.请求方式

    @app.route("login",method=["GET","POST"]) #在路由后面添加路由支持的请求方式
    

    2.获取请求参数

    @app.route("/login", methods=["GET", "POST"])
    def login():
        print(request.form) 
        print(request.url)
        print(request.url_charset)
        print(request.url_root)
        print(request.url_rule)
        print(request.values)
        print(request.values.to_dict())
        print(request.args.to_dict())
        data = {"username": "tony"}
        return jsonify(data)
    

    request.form ,获取formdata中的数据
    to_dict(),如果类型是ImmutableMultiDict,都可以用to_dict()
    request.url,获取请求的完整url
    request.url_charset,获取请求url的编码方式
    request.url_root,获取请求url的ip和port
    request.url_rule,获取请求路由
    request.values,获取post、get请求的请求数据,包括url和formdata中的数据
    request.args,获取请求参数,类型是ImmutableMultiDict,支持to_dict(),get(key)

    3.上传文件、保存文件

    html文件部分

    <body>
    <form action="http://127.0.0.1:5000/upload" method="post" enctype="multipart/form-data">
        上传文件:<input type="file" name="my_file">
        <button type="submit">提交</button><br>
    </form>
    

    后端:

    @app.route("/upload", methods=["POST"])
    def upload():
        print(request.files)  # FileStorage对象是Flask的文件特殊对象
        # 打印结果:ImmutableMultiDict([('my_file', < FileStorage: '' ('application/octet-stream') >)])
        my_file = request.files.get("my_file")  # 获取FileStorage文件对象
        my_file.save(my_file.filename)  # 保存文件
        return "200 ok"
    

    4.其他数据
    request.headers
    request.cookies
    request.path==request.url_rule
    request.host
    request.host_url

    5.特殊的提交方式获取
    content-type:application/json
    这时,request.form、request.arg是没有数据,放在request.json中
    request.json:获取content-type:application/json 时提交的数据

    content-type无法被识别时,放在request.data中
    request.data:获取content-type无法被识别或不包括有form字眼,原始请求中的数据 b''

    6.登录示例:
    前端:

    <body>
    <form action="http://127.0.0.1:5000/login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="pwd"><br>
        <button type="submit">提交</button><br>
    </form>
    

    flask

    @app.route("/index")
    def index():
        return "欢迎进入首页"
    
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            return render_template("login.html")
        if request.method == "POST":
            if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
                return redirect("/index")
            else:
                return "error,用户名或密码错误"
    

    Flask session

    Session 服务器端键值对
    Cookie 客户端的键值对

    flask的session交由客户端保管机制:
    1.开启session[username]=123
    {
    username:123
    }
    2.序列化字典==字符串
    3.加密字符串SecretKey 密钥字符串

    接收反序列化session
    1.从cookie中获取到一个叫session key的值
    eyJ1c2VyIjoibHR4In0.Y2vCsg.VQloai4PfMQHN_gOp_bLUvdaEkQ
    2.通过SecretKey 解密session
    3.反序列化成字典

    @app.route("/index")
    def index():
        if session.get("user")=="ltx": #判断session的用户名是否正确
            print(session.get("user"))
            return "欢迎进入首页"
        else:
            return redirect("/login")
    
    
    @app.route("/login", methods=["GET", "POST"])
    def login():
        if request.method == "GET":
            return render_template("login.html")
        if request.method == "POST":
            if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
                session["user"]=request.form.get("username") #新增session
                return redirect("/index")
            else:
                return "error,用户名或密码错误"
    

    Jinja2

    {{}} 引用变量参数
    {%%} 逻辑代码
    

    jinja2的简单实用:变量、循环、if判断

    # 模拟数据库
    STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
    
    STUDENT_LIST = [
        {'name': 'Old', 'age': 38, 'gender': '中'},
        {'name': 'Tony', 'age': 31, 'gender': '男'},
        {'name': 'EDU', 'age': 39, 'gender': '女'}
    ]
    
    STUDENT_DICT = {
        1: {'name': 'Old', 'age': 38, 'gender': '中'},
        2: {'name': 'Tony', 'age': 31, 'gender': '男'},
        3: {'name': 'EDU', 'age': 39, 'gender': '女'}
    }
    

    stuinfo.html

    <body>
        {{stu_info}}
    
        <table border="1">
            <tr>
                <td>name</td>
                <td>age</td>
                <td>gender</td>
            </tr>
            <tr>
                <td>{{stu_info.name}}</td>
                <td>{{stu_info.get("age")}}</td>
                <td>{{stu_info["gender"]}}</td>
            </tr>
        </table>
        {{stu_list}}
        <table border="1">
            <tr>
                <td>name</td>
                <td>age</td>
                <td>gender</td>
            </tr>
            {% for stu in stu_list %} <!--for循环-->
            <tr>
                <td>{{stu.name}}</td>
                <td>{{stu.get("age")}}</td>
                <td> <!--if判断-->
                    {% if stu["gender"]!='男' and stu["gender"]!='女'%}
                    酷儿
                    {% else %}
                        {{stu["gender"]}}
                    {% endif %} <!--if结束-->
                </td>
            </tr>
            {% endfor %} <!--for循环结束-->
        </table>
        {{stu_dict}}
        <table border="1">
                <tr>
                    <td>id</td>
                    <td>name</td>
                    <td>age</td>
                    <td>gender</td>
                </tr>
            {% for foo,item in stu_dict.items() %}
            <tr>
                <td>{{foo}}</td>
                <td>{{item.name}}</td>
                <td>{{item.age}}</td>
                <td>{{item.gender}}</td>
            </tr>
            {% endfor %}
        </table>
    </body>
    

    flask

    # 1.查看STUDENT放在studentinfo页面
    @app.route("/stu")
    def stu():
        return render_template("stuinfo.html", stu_info=STUDENT,stu_list=STUDENT_LIST,stu_dict=STUDENT_DICT)
    
    

    可以自己创建一个标签,传入参数:


    image.png

    Day2

    Flask路由参数

    1.endpoint
    不能重复,对应视图函数 ,endpoint默认是视图函数名。
    请求时,通过路由找到endpoint,再通过endpoint找到对应的视图函数。

    是否能反向操作,能通过endpoint找回路由吗?
    通过url_for反向创建路由。

    @app.route("/look_test", endpoint="/look")
    def look():
        print(url_for("/look")) # 通过endpoint找到路由,所以结果是:/look_test
        return "999"
    

    2.methods
    支持的请求方式,列表形式:methods=["GET","POST"]

    3.redirect_to
    永久重定向,308,没有进入到视图层面直接跳转。

    正常情况下:
    请求-->路由匹配-->通过路由找到endpoint-->通过endpoint找到视图函数

    redirect_to:
    请求-->路由匹配时,发现有redirect_to,立即返回,不用再走后面的部分。

    应用场景:当前地址不存在时,直接给你跳转到redirect_to的地址。api发生变更了,老用户没有新的访问地址,可以使用redirect_to。

    4.strict_slashes
    对url最后的/是否严格。
    strict_slashes=True严格:url最后的有/不能访问,404
    strict_slashes=False不严格:url最后的有/也可以访问

    5.default
    默认参数,如果有默认参数,视图函数中一定要接收参数,否则就会异常。

    6.动态参数
    <类型:变量>
    类型:int string

    @app.route("/look/<int:page>",methods=["GET"])
    def look(page):
        print(page)
        return "这是第{}页".format(page)
    

    访问:http://127.0.0.1:5000/look/10

    @app.route("/look/<folder>/<filename>", methods=["GET"])
    def look(folder, filename):
        filepath = os.path.join(folder, filename)
        return send_file(filepath)
    

    传入不带类型的,不写默认为string

    @app.route("/look/<folder>/<filename>", methods=["GET"])
    def look(folder, filename):
        filepath = os.path.join(folder, filename)
        return send_file(filepath)
    

    Flask 初始化(实例化)配置

    app = Flask(__name__)从Flask跳转进去,init参数如下:


    1.template_folder
    template模板路径,默认为templates
    app = Flask(__name__,template_folder="templates_new")
    

    2.static_folder
    静态文件路径,默认为static,static_folder的实现方式就是send_file。

    在根目录下新建staticimage文件夹,分别方上1.jpg和2.jpg
    访问:http://127.0.0.1:5000/image/2.jpg,报错404,
    访问:http://127.0.0.1:5000/static/1.jpg,展示图片,跟send_file效果一样。
    修改static_folder路径app = Flask(__name__,static_folder="image"),访问:http://127.0.0.1:5000/image/2.jpg,展示图片,而访问:http://127.0.0.1:5000/static/1.jpg报错404。

    3.static_url_path
    静态文件访问路径,默认值是static_folder

    4.static_host
    静态文件访问服务,比如:
    <img src="/static/2.jpg" alt="">也能访问到图片,因为自动拼接出host。

    Flask config配置

    1.app.default_config 默认配置

    default_config = ImmutableDict(
            {
                "ENV": None,
                "DEBUG": None,
                "TESTING": False,
                "PROPAGATE_EXCEPTIONS": None,
                "SECRET_KEY": None,
                "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
                "USE_X_SENDFILE": False,
                "SERVER_NAME": None,
                "APPLICATION_ROOT": "/",
                "SESSION_COOKIE_NAME": "session",
                "SESSION_COOKIE_DOMAIN": None,
                "SESSION_COOKIE_PATH": None,
                "SESSION_COOKIE_HTTPONLY": True,
                "SESSION_COOKIE_SECURE": False,
                "SESSION_COOKIE_SAMESITE": None,
                "SESSION_REFRESH_EACH_REQUEST": True,
                "MAX_CONTENT_LENGTH": None,
                "SEND_FILE_MAX_AGE_DEFAULT": None,
                "TRAP_BAD_REQUEST_ERRORS": None,
                "TRAP_HTTP_EXCEPTIONS": False,
                "EXPLAIN_TEMPLATE_LOADING": False,
                "PREFERRED_URL_SCHEME": "http",
                "JSON_AS_ASCII": None,
                "JSON_SORT_KEYS": None,
                "JSONIFY_PRETTYPRINT_REGULAR": None,
                "JSONIFY_MIMETYPE": None,
                "TEMPLATES_AUTO_RELOAD": None,
                "MAX_COOKIE_SIZE": 4093,
            }
        )
    

    DEBUG 开启代码编辑时重启、Log打印级别最低、错误信息透传
    TESTING 无限接近生产、不会开启代码编辑重启、Log打印级别较高、错误信息不透传
    SECRET_KEY 设置secret_key,生成session,前面说过

    app.config["SECRET_KEY"]="@@#!#!@"
    app.secret_key="@@#!#!@"
    # 效果都是一样的,但app.config["SECRET_KEY"]是直接改配置,效率更高
    

    PERMANENT_SESSION_LIFETIME session的生命周期,默认是31天,如果修改值的话,单位是秒,默认值timedelta(days=31)代表31天对应的秒。app.config["PERMANENT_SESSION_LIFETIME"]=3600*24

    SESSION_COOKIE_NAME 存放在浏览器cookie中session名,第一个字符不能是空格

    JSONIFY_MIMETYPE jsonify的标准格式,前面有说过

    2.Flask 快速配置
    使用app.config.from_object()快速切换不同环境配置

    在settting.py存放各项配置

    class DebugConfig: # 开发环境
        DEBUG = True
        SECRET_KEY = "123!@#$%%^"
    
    
    class TestingConfig: # 测试环境
        DEBUG = False
        SECRET_KEY = "正式环境需要一个很复杂的SECRET_KEY"
    

    导入 from setting import DebugConfig,TestingConfig,使用app.config.from_object(TestingConfig)或app.config.from_object(DebugConfig)就能快速切换不同环境的配置

    from flask import Flask
    from setting import DebugConfig,TestingConfig
    app = Flask(__name__)
    app.config.from_object(TestingConfig)
    
    
    @app.route("/index")
    def index():
        return "欢迎你呀"
    
    if __name__ == '__main__':
        app.run()
    

    BluePrint 蓝图

    蓝图的作用是 :功能隔离、路由隔离

    1.蓝图示例一:

    根目录下,有程序的入口:s2-bp.py,其他的模块app_01

    s2-bp.py

    from flask import Flask
    app = Flask(__name__)
    
    # 建立蓝图注册
    from app_01.views import user
    app.register_blueprint(user)
    
    if __name__ == '__main__':
        app.run()
    

    在app_01下views.py文件

    from flask import Blueprint
    
    # BluePrint 当作一个不能run的Flask实例
    
    user = Blueprint("user", __name__)  # 参数:先是蓝图的名字
    
    
    @user.route("/login")
    def login():
        return "BP login"
    

    此时访问:127.0.0.1:5000/login ,返回BP login

    2.蓝图示例二

    多个模块有同个路由,比如一个模块app_01是管理后台的登录接口,一个模块app_02有C端用户登录接口。使用url_prefixurl前缀参数解决。

    s2-bp.py

    from flask import Flask
    app = Flask(__name__)
    
    # 蓝图 建立蓝图注册
    from app_01.views import user
    from app_02.views import app_user
    app.register_blueprint(user)
    app.register_blueprint(app_user)
    
    if __name__ == '__main__':
        app.run()
    

    app_01下的views.py

    from flask import Blueprint
    
    user = Blueprint("user", __name__,url_prefix="/admin")  # 添加前缀
    
    
    @user.route("/login")
    def login():
        return "admin 管理端 BP login"
    

    app_02下的views.py

    from flask import Blueprint
    
    app_user = Blueprint("app_user", __name__,url_prefix="/shop") 
    
    @app_user.route("/login")
    def login():
        return "shop商城 BP login"
    

    在访问路由时,加上对应的前缀,如:
    访问http://127.0.0.1:5000/shop/login,是访问app_02中的login
    访问http://127.0.0.1:5000/admin/login是访问app_01中的login

    Flask 特殊装饰器

    @app.before_request
    @app.after_request
    @app.errorhandler(4xx or 5xx)

    1.@app.before_request 请求进入视图函数之前
    2.@app.after_request 请求结束,返回响应客户端之前

    定义函数的顺序:be1--be2--be3--af1--af2--af3

    正常 : be1--be2--be3--vf--af3--af2--af1

    异常: be1--be2--阻断--af3--af2--af1

    3.@app.errorhandler(4xx or 5xx) 自定义错误处理

    @app.errorhandler(404)
    def error404(ErrorMassage):
        print(ErrorMassage)
        return "页面{}不存在".format(request.path)
    

    Flask endpoint补充

    没懂 有机会再学

    Day3

    Flask 蓝图结构

    1.回顾蓝图
    前面翻翻吧

    2.一个简单的蓝图结构
    根目录下新建一个app01文件夹:
    -static
    -templates
    -views
    -models.py

    根目录下新建一个manage.py文件

    在app01下的__init__.py文件中:

    from flask import Flask
    from app01.views.user import user_bp
    
    def create_app():
        app = Flask(__name__)
        # 配置
        app.config["DEBUG"]=True
        # 注册蓝图
        app.register_blueprint(user_bp)
        return app
    

    views下的user.py

    from flask import Blueprint
    
    user_bp = Blueprint("user", __name__)
    
    
    @user_bp.route("/login")
    def login():
        return "登陆成功"
    
    

    根目录下manage.py

    from app01 import create_app
    app=create_app()
    if __name__ == '__main__':
        app.run()
    

    __init__.py文件创建Flask实例、配置config、注册蓝图
    在manage.py调用app.run()方法
    views.py 注册路由、视图函数

    使用python manage,py启动项目。

    Flask CBV

    flask中有两种视图,一种是基于函数的视图FBV,一种是基于类的视图CBV

    flask视图函数注册路由的本质:
    其实,route装饰器内部也是通过调用add_url_rule()方法实现的路由注册,只是route装饰器看起来更加美观。

    from flask import Flask, views  # 导入CBV的视图基类
    
    app = Flask(__name__)
    
    
    class Login(views.MethodView):  # 继承CBV视图基类的最高类
        def get(self):  # get方法的视图函数实现
            return "GET OK 200"
    
        def post(self):
            return "POST OK 200"
    
    
    # 为CBV添加路由
    app.add_url_rule("/login", view_func=Login.as_view(name="login"))
    
    if __name__ == '__main__':
        app.run()
    
    

    as_view 把视图类转化为视图函数

    Flask 监听端口 数据传递

    app.run("127.0.0.1",5000)

    IP对应本机访问IP,如果是0.0.0.0表示本机所有IP

    端口对应应用程序

    应用层:
    浏览器-端口9528,对应用192.168.14.26:9527发起请求时,传递了b'' HTTP 1.1 / GET\t\n

    网卡b'' HTTP 1.1 / GET\t\n 传递给操作系统
    操作系统 解包 根据端口9527--传递给9527
    WSGI:9527收到b'' HTTP 1.1 / GET\t\n ,Flask让WSGI把这些数据转换成对象environ
    Flask收到WSGI转换的environ对象request_class(request类),转换为Flask的request样式,比如请求参数,转换为request.form

    Flask-session

    第三方组件

    flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存(交给客户端保管不安全),该组件则将支持session保存到多个地方,如:

    • redis
    • memcached
    • filesystem
    • mongodb
    • sqlalchmey

    安装pip install Flask-session

    def create_app():
        app = Flask(__name__)
        # 配置
        app.config["DEBUG"] = True
        # 在config配置之后,在注册蓝图之前,是三方组件的空间
        # 实例化一个session
        Session(app)
    
        # 注册蓝图
        app.register_blueprint(user_bp)
        return app
    

    SESSION_SQLALCHEMY 数据库ORM

    # session存储在redis
    app.config["SESSION_TYPE"]='redis'
    # 实例化
    Session(app)
    
    # 在login方法中设置session
    class Login(views.MethodView):  # 继承CBV视图基类的最高类
        def get(self):  # get方法的视图函数实现
            session["username"]="电地大"
            return "GET OK 200"
    

    Redis模块的简单用法

    redis安装
    https://redis.io/download/
    启动服务

    from redis import Redis
    
    rdb=Redis()
    rdb.set("username","NB")
    
    print(rdb.get("username"))
    

    存一个字典

    rdb=Redis()
    d={"key":"value"}
    # 把dict转为byte
    rdb.set("username",json.dumps(d))
    # 把byte转为dict
    print(json.loads(rdb.get("username")))
    

    db参数:

    rdb=Redis(host="127.0.0.1",port=6379,db=8) # db-->0-15,除了0,其他都会显示,数据隔离的作用
    

    在redis服务中命令select 8

    Flask-session高级源码阅读

    看不懂 就这样吧。

    app.config["SESSION_TYPE"] = 'redis'
    app.config["SESSION_REDIS"] = Redis(host="192.168.14.25")  # 实例化,部署在内网的其他服务器
    Session(app)
    

    Day4

    Flask请求上下文预备知识

    1.线程安全
    2.偏函数
    3.OOP 面向对象

    面向对象回顾

    偏函数

    简单的理解偏函数,它是对原始函数的二次封装,是将现有函数的部分参数预先绑定为指定值,从而得到一个新的函数,该函数就称为偏函数。相比原函数,偏函数具有较少的可变参数,从而降低了函数调用的难度。

    from functools import partial
    
    def abfun(a, b):
        print(a)
        print(b)
        return a + b
    
    
    new_ab = partial(abfun, 2, 3)
    print(new_ab)  # functools.partial(<function abfun at 0x000001BA7781D0D8>, 2, 3)
    print(new_ab())  # 5
    

    将原函数和原函数接收的参数一并存放,返回新函数,在执行新函数时,将参数传入原函数中一并执行。

    from functools import partial
    
    def abfun(a, b,x):
        print(a)
        print(b)
        return a + b+x
    # 只知道一个参数的值
    new_ab = partial(abfun,x=80)
    print(new_ab)
    print(new_ab(3,10))  # 93
    

    线程安全

    单线程读取19个,需要19s,打印内容为012345...19

    import time
    
    class Foo:
        pass
    
    f = Foo()
    f.num = 0
    
    
    def add(i):
        f.num = i
        # 模拟IO操作需要1s
        time.sleep(1)
        print(f.num)
    
    
    for i in range(20):
        add(i)
    

    开启多线程,使任务在1.5s左右完成:
    但打印的结果是19 19 19...19

    import time
    from threading import Thread
    
    class Foo:
        pass
    
    
    f = Foo()
    
    f.num = 0
    
    
    def add(i):
        f.num = i
        time.sleep(1)
        print(f.num)
    
    
    for i in range(20):
        task=Thread(target=add,args=(i,))
        task.start()
    

    使用深copy:

    很快解决了阻塞 保证了公共对象的安全性
    但浪费了大量的资源 拿空间浪费换取时间

    import time
    from threading import Thread,get_ident
    from copy import deepcopy
    class Foo:
        pass
    
    
    f = Foo()
    
    f.num = 0
    local_dict={}
    
    def add(i):
        # 深copy
        local_dict[get_ident()]=deepcopy(f)
        local_dict[get_ident()].num = i
        time.sleep(1)
        print("{}_{}".format(local_dict[get_ident()].num,get_ident()))
        # print(get_ident())
    
    for i in range(20):
        task=Thread(target=add,args=(i,))
        task.start()
    
    
    

    WSGI收取request

    请求上下文:读flask源码
    1.请求是如何到达flask应用的


    由底层传到高层

    请求上文

    from werkzeug.wrappers import Request,Response
    from werkzeug import run_simple
    # run_simple监听操作系统传递来的数据
    @Request.application
    def app(req):
        print(req,req.method,type(req))
        return Response("200 ok")
    
    run_simple("127.0.0.1",5000,app)
    

    打印结果:

    req # <Request 'http://127.0.0.1:5000/' [GET]> 
    req.method # GET 
    type(req) #<class 'werkzeug.wrappers.request.Request'>
    

    falsk中的app.run()调用的就是run_simple()方法
    一顿转换,转换为flask风格的request

    image.png

    environ是原始的请求信息,app

    golbals.py中 --》请求上文


    image.png

    请求下文

    相关文章

      网友评论

          本文标题:flask-16day

          本文链接:https://www.haomeiwen.com/subject/fsbbtdtx.html