【Flask从入门到精通:第三课:http的请求与响应】

07-16 697阅读

http的请求与响应

flask的生命周期

客户端—>wsgi应用程序->全局钩子–> 路由 --> 视图 --> 路由—> 全局钩子 —> wsgi应用程序—> 客户端

【Flask从入门到精通:第三课:http的请求与响应】
(图片来源网络,侵删)

请求

文档: https://flask.palletsprojects.com/en/2.0.x/api/#flask.Request

  • request:flask中代表当前请求的 request 对象
  • 作用:在视图函数中取出本次客户端的请求数据
  • 导入:from flask import request
  • 代码位置:
  • ​ 代理类 from flask.app import Request —> from flask.globals.Request
  • ​ 源码类:from flask.wrappers.Request
  • ​ 基类:from werkzeug.wrappers import Request as RequestBase

    request,常用的属性如下:

    属性说明类型
    data记录请求体的数据,并转换为字符串
    只要是通过其他属性无法识别转换的请求体数据
    最终都是保留到data属性中
    例如:有些公司开发微信小程序,原生IOS或者安卓,这一类客户端有时候发送过来的数据就不一样是普通的表单,查询字符串或ajax
    bytes类型
    form记录请求中的html表单数据ImmutableMultiDict
    args记录请求中的查询字符串,也可以是query_stringImmutableMultiDict
    cookies记录请求中的cookie信息Dict
    headers记录请求中的请求头ImmutableMultiDict
    method记录请求使用的HTTP方法GET/POST
    url记录请求的URL地址string
    files记录请求上传的文件列表ImmutableMultiDict
    json记录ajax请求的json数据Dict
    获取请求中各项数据

    获取查询字符串,代码:

    from flask import Flask, request
    from werkzeug.datastructures import ImmutableMultiDict
    from werkzeug.wrappers import Request as RequestBase
    from flask.wrappers import Request
    # 项目实例应用对象
    app = Flask(__name__)
    # 加载配置
    app.config.update({
        "DEBUG": True
    })
    # 在http的常用请求方法中,delete和get是没有请求体的!!!
    @app.route(rule="/data", methods=["post", "put", "patch"])
    def data():
        """获取请求体"""
        # 获取原生的请求体数据[当request对象的其他属性没法接受请求体数据时,会把数据保留在data中,如果有request对象的属性处理了请求体数据,则data就不再保留]
        # print(request.data)  # 如果客户端上传的是xml文档,html格式,二进制流格式,base64格式,就要使用data来接收
        """
        1. 没有上传任何数据:
            b''
        2. 上传json数据
            b'{\n    "username": "xiaoming",\n    "age": 16\n}'
        3. 上传表单数据
            b''
        4. 上传xml数据
            b'\n    \xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x981\n    \xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x982\n'
        """
        # 接收表单上传的数据
        # print(request.form)
        """
        ImmutableMultiDict([('name', '小明'), ('age', '19')])
        """
        # 接收ajax上传的json数据
        # print(request.json)     # {"username": "xiaoming", "age": 16}
        # print(request.is_json)  # True 往往用于判断是否是ajax请求
        # 上传文件列表 HTML必须以 # 表单属性才能上传文件
        # print(request.files)
        """
        ImmutableMultiDict([('avatar', )])
        """
        # 接受上传文件
        # avatar = request.files["avatar"]
        # print(avatar)
        """
        
        from werkzeug.datastructures import FileStorage
        FileStorage,上传文件处理对象,flask封装的一个上传文件处理对象,可以允许我们直接调用对应的方法进行文件的存储处理, 
        也可以结合其他的ORM模块像djangoORM那样通过模型操作对上传自动存储处理
        """
        # 处理上传文件[一般不会这么做!!!而是采用专业的第三方存储设备来存储,]
        # from pathlib import Path
        # save_path = str(Path(__file__).parent / "uploads/avatar.jpeg")
        # avatar.save(save_path)
        # 获取请求头信息
        print(request.headers)  # 获取全部的而请求头信息
        print(request.headers.get("Host"))  # 127.0.0.1:5000,客户端请求地址,也相当于服务器地址
        # 获取客户端发送过来的自定义请求头
        print(request.headers.get("company"))  # beijing,不存在的键的结果:None,存在则得到就是值,
        print(request.headers.get("token"))    # jwt...xxx
        # 获取客户端的请求头中的相关数据
        print(request.user_agent)   # 用户访问服务器时使用的网络代理,一般就是浏览器标记信息,PostmanRuntime/7.26.10
        print(request.remote_addr)  # 客户端远程地址
        print(request.server)       # 服务端的端点,格式:(IP, 端口)
        # 获取请求方法
        print(request.method)  # POST
        # 本次请求的url地址
        print(request.url)  # http://127.0.0.1:5000/data
        print(request.root_url)  # 根路径
        print(request.path)      # /data
        return "获取请求体"
    if __name__ == '__main__':
        app.run()
    

    获取请求体,代码:

    from flask import Flask, request
    from werkzeug.datastructures import ImmutableMultiDict
    from werkzeug.wrappers import Request as RequestBase
    from flask.wrappers import Request
    # 项目实例应用对象
    app = Flask(__name__)
    # 加载配置
    app.config.update({
        "DEBUG": True
    })
    # 在http的常用请求方法中,delete和get是没有请求体的!!!
    @app.route(rule="/data", methods=["post", "put", "patch"])
    def data():
        """获取请求体"""
        # 获取原生的请求体数据[当request对象的其他属性没法接受请求体数据时,会把数据保留在data中,如果有request对象的属性处理了请求体数据,则data就不再保留]
        # print(request.data)  # 如果客户端上传的是xml文档,html格式,二进制流格式,base64格式,就要使用data来接收
        """
        1. 没有上传任何数据:
            b''
        2. 上传json数据
            b'{\n    "username": "xiaoming",\n    "age": 16\n}'
        3. 上传表单数据
            b''
        4. 上传xml数据
            b'\n    \xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x981\n    \xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x982\n'
        """
        # 接收表单上传的数据
        # print(request.form)
        """
        ImmutableMultiDict([('name', '小明'), ('age', '19')])
        """
        # 接收ajax上传的json数据
        # print(request.json)     # {"username": "xiaoming", "age": 16}
        # print(request.is_json)  # True 往往用于判断是否是ajax请求
        # 上传文件列表 HTML必须以 # 表单属性才能上传文件
        # print(request.files)
        """
        ImmutableMultiDict([('avatar', )])
        """
        # 接受上传文件
        # avatar = request.files["avatar"]
        # print(avatar)
        """
        
        from werkzeug.datastructures import FileStorage
        FileStorage,上传文件处理对象,flask封装的一个上传文件处理对象,可以允许我们直接调用对应的方法进行文件的存储处理, 
        也可以结合其他的ORM模块像djangoORM那样通过模型操作对上传自动存储处理
        """
        # 处理上传文件[一般不会这么做!!!而是采用专业的第三方存储设备来存储,]
        # from pathlib import Path
        # save_path = str(Path(__file__).parent / "uploads/avatar.jpeg")
        # avatar.save(save_path)
        # 获取请求头信息
        print(request.headers)  # 获取全部的而请求头信息
        print(request.headers.get("Host"))  # 127.0.0.1:5000,客户端请求地址,也相当于服务器地址
        # 获取客户端发送过来的自定义请求头
        print(request.headers.get("company"))  # beijing,不存在的键的结果:None,存在则得到就是值,
        print(request.headers.get("token"))    # jwt...xxx
        # 获取客户端的请求头中的相关数据
        print(request.user_agent)   # 用户访问服务器时使用的网络代理,一般就是浏览器标记信息,PostmanRuntime/7.26.10
        print(request.remote_addr)  # 客户端远程地址
        print(request.server)       # 服务端的端点,格式:(IP, 端口)
        # 获取请求方法
        print(request.method)  # POST
        # 本次请求的url地址
        print(request.url)  # http://127.0.0.1:5000/data
        print(request.root_url)  # 根路径
        print(request.path)      # /data
        return "获取请求体"
    if __name__ == '__main__':
        app.run()
    

    响应

    flask默认支持2种响应方式:

    数据响应: 默认响应html文本,也可以返回 JSON格式,或其他格式

    页面响应: 重定向

    ​ url_for 视图之间的跳转

    响应的时候,flask也支持自定义http响应状态码

    响应html文本
    from flask import Flask,make_response, Response
    app = Flask(__name__)
    app.config.update({
        "DEBUG": True
    })
    @app.route("/")
    def index():
        # 默认返回的就是HTML代码,在flask内部调用视图时,得到的返回值会被flask判断类型,
        # 如果类型不是response对象,则视图的返回值会被作为response对象的实例参数返回客户端
        # return "

    hello

    ", 400, {"company": "python"} # return make_response("

    hello

    ", 400, {"company": "python"}) return Response(f"默认首页", 201, {"company": "python"}) if __name__ == '__main__': app.run()
    返回JSON数据

    在 Flask 中可以直接使用 jsonify 生成一个 JSON 的响应

    from flask import Flask, jsonify
    from decimal import Decimal
    app = Flask(__name__)
    app.config.update({
        "DEBUG": True,
        "JSONIFY_PRETTYPRINT_REGULAR": False,
    })
    @app.route("/")
    def index():
        # """返回json格式数据,返回json字典"""
        # data = {"name":"xiaoming","age":16}
        # return data
        # """返回json格式数据,返回各种json数据,包括列表"""
        data = [
            {"id": 1, "username": "liulaoshi", "age": 18},
            {"id": 2, "username": "liulaoshi", "age": 17},
            {"id": 3, "username": "liulaoshi", "age": 16},
            {"id": 4, "username": "小明", "age": Decimal(15)},
        ]
        return jsonify(data)
    if __name__ == '__main__':
        app.run()
    

    flask中返回json 数据,都是flask的jsonify方法返回就可以了,直接return只能返回字典格式的json数据。

    重定向

    重定向到站点地址

    from flask import Flask, redirect
    # 应用实例对象
    app = Flask(__name__)
    @app.route("/")
    def index():
        """页面跳转"""
        """
        301: 永久重定向,页面已经没有了,站点没有了,永久转移了。
        302:临时重定向,一般验证失败、访问需要权限的页面进行登录跳转时,都是属于临时跳转。
        """
        # redirect函数就是response对象的页面跳转的封装
        # response = redirect("http://www.qq.com", 302)
        # redirect的原理,最终还是借助Resonse对象来实现:
        response = "", 302, {"Location": "http://www.163.com"}
        return response
    if __name__ == '__main__':
        # 启动项目的web应用程序
        app.run(host="0.0.0.0", port=5000, debug=True)
    
    重定向到自己写的视图函数

    可以直接填写自己 url 路径

    也可以使用 url_for 生成指定视图函数所对应的 url

    from flask import url_for

    @app.route("/info")
    def info():
        return "info"
    @app.route("/user")
    def user():
        url = url_for("info")
        print(url)
        return redirect(url)
    
    重定向到带有路径参数的视图函数

    在 url_for 函数中传入参数

    from flask import Flask, redirect, url_for
    # 应用实例对象
    app = Flask(__name__)
    @app.route("/demo/")
    def mobile(mob):
        print(mob)
        return f"mobile={mob}"
    @app.route("/sms")
    def sms():
        """携带路径参数进行站内跳转"""
        # url_for("视图方法名", 路由路径参数)
        url = url_for("mobile", mob=13312345678)
        print(url)
        return redirect(url)
    if __name__ == '__main__':
        # 启动项目的web应用程序
        app.run(host="0.0.0.0", port=5000, debug=True)
    
    自定义状态码和响应头

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

    from flask import Flask, redirect, url_for, make_response, Response
    # 应用实例对象
    app = Flask(__name__)
    @app.route("/rep")
    def rep():
        """常用以下写法"""
        return "ok", 201, {"Company":"python-35"}
        # """原理"""
        # response = make_response("ok", 201, {"Company": "python-35"})
        # return response
        #
        # """原理"""
        # response = Response("ok")
        # response.headers["Company"] = "oldboy" # 自定义响应头
        # response.status_code = 201             # 自定义响应状态码
        # return response
    if __name__ == '__main__':
        # 启动项目的web应用程序
        app.run(host="0.0.0.0", port=5000, debug=True)
    
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]