处理http的请求与响应

一、flask的生命周期

 

 

web 服务器: app.run() / nginx / uwsgi
wsgi: app=Flask() / django-application 
全局钩子(权限验证、访问日志等): @app.before_request / django-中间键
路由: @app.route()
视图:默认函数视图+类视图, 最终转换为一个request,这里可以处理数据,操作数据库等

二、请求

1.request的常用属性

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

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

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

  • 导入from flask import request

  • 源码位置

  • 代理类 from flask import request --来源-> from flask.globals import request

  • 源码类:from flask.wrappers import Request

  • 基类:from werkzeug.wrappers import Request as RequestBase

request,常用的属性如下:

属性说明类型
data 记录请求体的数据,并转换为字符串 只要是通过其他属性无法识别转换的请求体数据 最终都是保留到data属性中 例如:有些公司开发微信小程序,原生IOS或者安卓,这一类客户端有时候发送过来的数据就不一定是普通的form表单或查询字符串或json 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

 

2.获取请求中各项数据

1)获取查询字符串,代码:

from flask import Flask, request
from urllib.parse import parse_qs
​
​
app = Flask(__name__)
​
​
@app.route("/qs")
def qs():
    """
    获取客户端请求的查询字符串参数
    :return:
    """
    """
    请求url:http://127.0.0.1:5000/qs?user=xiaoming&age=16
    """
    # 获取原始的查询字符串参数,格式:bytes
    # print(request.query_string)
    # b'user=xiaoming&age=16'
# # 针对原始的查询字符串参数,转换成字典格式
    # query_string = parse_qs(request.query_string.decode())
    # print(query_string)  # {'user': ['xiaoming'], 'age': ['16']}
# # 获取参数值
    # print(query_string["user"][0])
​
​
    # # 获取查询字符串参数,格式:ImmutableMultiDict
    # print(request.args)
    # # ImmutableMultiDict([('user', 'xiaoming'), ('age', '16')])
# # 获取单个参数值
    # print(request.args["user"])
    # print(request.args["age"])
    # print(request.args.get("age"))
​
​
    """
    请求url:http://127.0.0.1:5000/qs?user=xiaoming&fav=shopping&fav=coding&fav=rap
    """
    # print(request.args["user"]) # 'xiaoming'
    # print(request.args["fav"])  # 'shopping'
    # print(request.args.get("user")) # 'xiaoming'
print(request.args.getlist("fav"))  # ['shopping', 'coding', 'rap']
return "hello, flask"
​
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

2) 获取请求体,代码:

import json
​
from flask import Flask, request
​
​
app = Flask(__name__)
​
​
@app.route("/form1", methods=["post"])
def form1():
    """
    获取客户端请求的请求体[表单]
    :return:
    """
    """
    获取表单数据
    请求url:
    """
    """获取表单数据[不包含上传文件]"""
    # print(request.form)
    # # ImmutableMultiDict([('username', 'root'), ('password', '123456'), ('fav', 'swimming'), ('fav', 'watch TV')])
    # # 获取表单项数据[单个值]
    # print(request.form.get("username")) # root
    # # 获取表单项数据[多个值]
    # print(request.form.getlist("fav"))  # ['swimming', 'watch TV']
​
​
    """获取表单数据的上传文件"""
    # print(request.form.get("username"))
    # # 获取所有上传文件
    # print(request.files)  # ImmutableMultiDict([('avatar', <FileStorage: 's.png' ('image/png')>)])
    # # 根据name值获取单个上传文件
    # print(request.files.get("avatar"))  # <FileStorage: 's.png' ('image/png')>
    # # 根据name值获取多个上传文件
    # print(request.files.getlist("avatar"))  # [<FileStorage: 'a.png' ('image/png')>, <FileStorage: 's.png' ('image/png')>]
return "hello, flask"
​
​
@app.route("/data", methods=["post"])
def data():
    """
    获取客户端请求的请求体[ajax]
    :return:
    """
    """判断本次客户端是否是ajax请求获取本次客户端提交的数据格式是否是json"""
    # print(request.is_json)
"""获取客户端请求体中的json数据"""
    # print(request.json)  # {'username': 'root', 'password': '123456'}
"""获取客户端请求体的原始数据"""
    # print(request.data)  # b'{\n  "username": "root",\n  "password": "123456"\n}'
    # 原始数据转json格式
    # print(json.loads(request.data))  # {'username': 'root', 'password': '123456'}
"""接收其他格式类型的数据"""
    # print(request.data)
return "hello, flask"
​
​
@app.route("/file", methods=["post", "put", "patch"])
def file():
    """
    接收上传文件并保存文件
    :return:
    """
    avatar = request.files.get("avatar")
    print(avatar)
    # 调用FileStorage提供的save方法就可以保存文件了
    avatar.save("./avatar.png")
​
    return "hello, flask"
​
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

3)获取请求头等相关数据,代码:

import json
​
from flask import Flask, request
​
​
app = Flask(__name__)
​
@app.route("/header", methods=["get", "post", "put", "patch","delete"])
def header():
    """
    获取请求头等其他请求信息
    :return:
    """
    # # 获取请求头所有信息
    # print(request.headers, type(request.headers))
    #
    # """
    # 获取单个请求头信息
    # """
    # # 基于get使用请求头原始属性名获取, User-Agent 客户端的网络代理工具名称
    # print(request.headers.get("User-Agent"))  # PostmanRuntime/7.26.10
    # # 把原始属性名转换成小写下划线格式来获取
    # print(request.user_agent)   # PostmanRuntime/7.26.10
    #
    # # 获取本次客户端请求的服务端地址
    # print(request.host)  # 127.0.0.1:5000
    #
    # # 获取本次客户端请求提交的数据格式
    # print(request.content_type)  # multipart/form-data;
    #
    # # 获取本次客户端请求的uri路径
    # print(request.path)  # /header
    # # 获取本次客户端请求完整url地址
    # print(request.url)   # http://127.0.0.1:5000/header
    # # 获取本次客户端请求的服务端域名
    # print(request.root_url)  # http://127.0.0.1:5000/
    #
    # # 获取本次客户端的Http请求方法或请求动作
    # print(request.method)  # POST
    #
    # # 获取本次客户端的IP地址
    # print(request.remote_addr)  # 127.0.0.1
    #
    # # 获取本次客户端获取到的服务端信息
    # print(request.server)  # ('0.0.0.0', 5000)
# 获取本次客户端请求时,服务端的系统系统环境变量信息
    # print(request.environ)
"""
    获取自定义请求头
    """
    print(request.headers.get("company"))  # flask.edu
return "hello, flask"
​
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

二、响应

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

  • 数据响应: 默认响应html文本,也可以返回 JSON格式,或其他媒体类型的文件
  • 页面响应: 重定向,url_for 视图之间的跳转

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

1.响应html文本

from flask import Flask, make_response, Response

app = Flask(__name__)
​
​
@app.route("/")
def index():
    """响应HTML文本,并设置响应状态码"""
    # return "<h1>hello, flask</h1>", 400
"""通过make_response返回Response对象"""
    # response = make_response("<h1>hello, flask</h1>", 201)
    # print(response)
    # return response
"""通过Response返回Response对象"""
    response = Response("<h1>hello, flask</h1>", 201)
    return response
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)
​

2.返回JSON数据

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

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

import json
from flask import Flask, make_response, Response, jsonify
​
​
app = Flask(__name__)
​
@app.route("/jsonapi")
def jsonapi():
    """响应json数据[原生写法]"""
    data = {"name": "xiaoming", "age": 16}
    # return json.dumps(data), 200, {"Content-Type": "application/json"}
    # return Response(json.dumps(data), 200, {"Content-Type": "application/json"})
"""响应json数据[jsonify]"""
    data = {"name": "xiaoming", "age": 16}
    response = jsonify(data)
    print(response)
    return response
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

3.响应指定媒体类型的文件

import json
from flask import Flask, make_response, Response, jsonify​
app = Flask(__name__)
​
@app.route("/img")
def img():
    """响应图片格式给客户端"""
    with open("avatar.png", "rb") as f:
        data = f.read()
    return data, 200, {"Content-Type": "image/png"}  # MIME类型
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

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

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

from flask import Flask, request, redirect, url_for, Response


app = Flask(__name__)

@app.route("/")
def index():
    """自定义响应头"""
    return "hello, flask", 201, {"Company": "flask.edu"}


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

 

 

posted @ 2023-04-13 22:03  www.pu  Views(44)  Comments(0Edit  收藏  举报