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

http的请求与响应

flask的生命周期

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

请求

文档: 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_string ImmutableMultiDict
cookies 记录请求中的cookie信息 Dict
headers 记录请求中的请求头 ImmutableMultiDict
method 记录请求使用的HTTP方法 GET/POST
url 记录请求的URL地址 string
files 记录请求上传的文件列表 ImmutableMultiDict
json 记录ajax请求的json数据 Dict
获取请求中各项数据

获取查询字符串,代码:

python 复制代码
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'<goods-list>\n    <goods price="100">\xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x981</goods>\n    <goods price="200">\xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x982</goods>\n</goods-list>'
    """

    # 接收表单上传的数据
    # print(request.form)
    """
    ImmutableMultiDict([('name', '小明'), ('age', '19')])
    """

    # 接收ajax上传的json数据
    # print(request.json)     # {"username": "xiaoming", "age": 16}
    # print(request.is_json)  # True 往往用于判断是否是ajax请求

    # 上传文件列表 HTML必须以<form method="post" enctype="multipart/form-data"> # 表单属性才能上传文件
    # print(request.files)
    """
    ImmutableMultiDict([('avatar', <FileStorage: 'avatar.jpg' ('image/jpeg')>)])
    """

    # 接受上传文件
    # avatar = request.files["avatar"]
    # print(avatar)
    """
    <FileStorage: 'avatar.jpg' ('image/jpeg')>
    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()

获取请求体,代码:

python 复制代码
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'<goods-list>\n    <goods price="100">\xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x981</goods>\n    <goods price="200">\xe5\x95\x86\xe5\x93\x81\xe6\xa0\x87\xe9\xa2\x982</goods>\n</goods-list>'
    """

    # 接收表单上传的数据
    # print(request.form)
    """
    ImmutableMultiDict([('name', '小明'), ('age', '19')])
    """

    # 接收ajax上传的json数据
    # print(request.json)     # {"username": "xiaoming", "age": 16}
    # print(request.is_json)  # True 往往用于判断是否是ajax请求

    # 上传文件列表 HTML必须以<form method="post" enctype="multipart/form-data"> # 表单属性才能上传文件
    # print(request.files)
    """
    ImmutableMultiDict([('avatar', <FileStorage: 'avatar.jpg' ('image/jpeg')>)])
    """

    # 接受上传文件
    # avatar = request.files["avatar"]
    # print(avatar)
    """
    <FileStorage: 'avatar.jpg' ('image/jpeg')>
    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文本
python 复制代码
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 "<h1>hello</h1>", 400, {"company": "python"}
    # return make_response("<h1>hello</h1>", 400, {"company": "python"})
    return Response(f"默认首页", 201, {"company": "python"})


if __name__ == '__main__':
    app.run()
返回JSON数据

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

python 复制代码
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数据。

重定向

重定向到站点地址

python 复制代码
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

python 复制代码
@app.route("/info")
def info():
    return "info"

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

在 url_for 函数中传入参数

python 复制代码
from flask import Flask, redirect, url_for

# 应用实例对象
app = Flask(__name__)

@app.route("/demo/<int:mob>")
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

python 复制代码
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)
相关推荐
databook8 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar9 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户8356290780519 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_9 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机16 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机17 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机17 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机17 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i17 小时前
drf初步梳理
python·django
每日AI新事件17 小时前
python的异步函数
python