文章目录
请求对象
- Flask从环境变量中获取请求数据并储存在request代理对象上了,主要基于Request类实现
1. GET请求
- 获取get请求的参数:request.args
- 获取的数据类型:ImmutableMultiDict(不可变字典)
- 可以用 to_dict() 方法转换成普通的可变字典
@app.route('/')
def index():
r = request.args
print(r.get('id')) # 1
return r.to_dict() # json格式:{"id": 1}
curl -X GET "http://127.0.0.1:5000/?id=1"
{
"id": "1"
}
2. POST请求
- form
- 获取表单数据,请求头是:application/x-www-form-urlencoded
- 获取表单数据:request.form
- 获取的数据类型:ImmutableMultiDict(不可变字典)
@app.route('/', methods=['POST'])
def index():
return request.form
# post请求发送data格式数据
$ curl http://127.0.0.1:5000 -X POST -d 'id=1&name=zhangsan'
{
"id": "1",
"name": "zhangsan"
}
- json
- 获取json数据,请求头是:applocation/json
- 获取json数据:request.json
- 数据类型:普通字典dict类型,内部帮我们用json.loads(data)转换dict类型
- 其实内部是调用的get_json()方法
@app.route('/', methods=['POST'])
def index():
return request.json
# post请求发送json格式数据
$ curl http://127.0.0.1:5000 -X POST -d '{"id": "1","name":"zhangsan"}' -H "Content-Type:application/json"
{
"id": "1",
"name": "zhangsan"
}
3. 其他参数
- request.values
- 可以同时获取args参数和form表单参数
- 类型是CombinedMultiDict,内容是args和form
- 一样可根据字典的方法获取对应的参数名的值
@app.route('/', methods=['POST', 'GET'])
def index():
return request.values
# get请求
$ curl http://127.0.0.1:5000 -X GET -d 'id=1&name=zhangsan'
{
"id": "1",
"name": "zhangsan"
}
# post请求
$ curl http://127.0.0.1:5000 -X POST -d 'id=1&name=zhangsan'
{
"id": "1",
"name": "zhangsan"
}
- request.cookies
- 获取请求头的cookie数据,类型是dict
@app.route('/', methods=['POST', 'GET'])
def index():
return request.cookies
# cur命令发送cookie数据
$ curl http://127.0.0.1:5000 -X POST -d 'id=1&name=zhangsan' --cookie "user=root;pwd=123456"
{
"pwd": "123456",
"user": "root"
}
- request.headers
- 获取请求头类型dict
- request.data
- 包含传入的请求数据作为字符串,以防它与 Werkzeug无法处理mimetype。
- 可以获取json数据,但获取出来的数据类型bytes
- request.files:比较重要
- 获取post或put请求的文件
- 类型MultiDict
- request.environ
- 获取WSGI隐含的环境配置
- 可以获取request对象没有封装的数据
- request.method
- 获取请求方法
- request.remote_addr
- 获取远程ip
- 主要用于我们要限制ip的场景下
- reuqest.user_agent
- 获取请求头中的user-agent数据
- 可以做一些反扒和恶意攻击的处理
- request.is_json
- 判断mimetype是不是application开头,并且是json结尾
- 布尔类型
@app.route('/', methods=['POST'])
def index():
print(request.is_json) # True
return request.json
$ curl http://127.0.0.1:5000 -X POST -d '{"id": "1","name":"zhangsan"}' -H "Content-Type:application/json"
{
"id": "1",
"name": "zhangsan"
}
- request.is_xhr
- 判断是否ajax请求发来的(要废弃了)
- 可以通过request.environ[“HTTP_X_REQUESTED_WITH”] 来获取
但也不一定是ajax请求,因为前端数据可伪造
@app.route('/', methods=['POST'])
def index():
print(request.is_json) # True
print(request.headers) # True
print(request.user_agent) # curl/7.64.1
print(request.remote_addr) # 127.0.0.1
print(request.method) # POST
print(request.environ)
# {'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', 'wsgi.input': <_io.BufferedReader name=6>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>, 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'werkzeug.server.shutdown': <function WSGIRequestHandler.make_environ.<locals>.shutdown_server at 0x7fb1bcd12430>, 'SERVER_SOFTWARE': 'Werkzeug/1.0.1', 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_URI': '/', 'RAW_URI': '/', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': 61621, 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': '5000', 'SERVER_PROTOCOL': 'HTTP/1.1', 'HTTP_HOST': '127.0.0.1:5000', 'HTTP_USER_AGENT': 'curl/7.64.1', 'HTTP_ACCEPT': '*/*', 'CONTENT_TYPE': 'application/json', 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', 'CONTENT_LENGTH': '29', 'werkzeug.request': <Request 'http://127.0.0.1:5000/' [POST]>}
print(request.data) # b'{"id": "1","name":"zhangsan"}'
print(request.environ["HTTP_X_REQUESTED_WITH"] ) # XMLHttpRequest
return request.json
$ curl http://127.0.0.1:5000 -X POST -d '{"id": "1","name":"zhangsan"}' -H "Content-Type:application/json" -H 'X-Requested-With: XMLHttpRequest'
{
"id": "1",
"name": "zhangsan"
}
- ajax请求
@app.route('/', methods=['GET'])
def index():
return render_template('xhr.html')
@app.route('/login', methods=['POST'])
def login():
return request.json
<p onclick="login()">点一下试试</p>
<script type="text/javascript" src="../static/js/jquery-1.12.4.min.js"></script>
<script>
function login(){
$.ajax({
url:'/login',
type: 'post',
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({'username':'zhangsan', 'pwd': '123456'}),
}).done(function(data){
console.log(data)
});
};
</script>
响应对象
1. 响应类型Content-Type
- 文本:text/plain
- html:text/html。不进行任何设置时,浏览器会把响应返回的字符串变成html。
- xml:application/xml
- json:application/json
2. 手动构造响应返回
- 返回json串
@app.route('/', methods=['get'])
def index():
return json.dumps({'username': 'zhangsan', })
- jsonify()
@app.route('/', methods=['get'])
def index():
return jsonify({'username': 'zhangsan', })
- 构造修改响应
@app.route('/', methods=['get'])
def index():
return jsonify({'username': 'zhangsan', }), '204 ok', {'content-type':'application/json', 'server':'nginx'}
3. make_response()
- 初始化构造
@app.route('/', methods=['get'])
def index():
return make_response(json.dumps({"username": "jiangmingbai"}), '201 xx', {"content-type": "application/json"})
- 先定义后构造
@app.route('/', methods=['get'])
def index():
res = make_response()
res.response = json.dumps({"username": "jiangmingbai"})
res.status = '200 XX'
res.header = {'a': 'b'}
return res
4. json响应格式
+
json.dumps()
: <class ‘str’> ,且添加{'Content-Type': 'application/json'}
头信息之后才是json格式
+jsonify()
: <class ‘flask.wrappers.Response’>
@app.route('/', methods=['get'])
def index():
print(type(json.dumps({"username": "lis"}))). # <class 'str'>
return json.dumps({"username": "lis"}), '202 OK', {'Server':'nginx', 'Content-Type': 'application/json'}
@app.route('/l', methods=['get'])
def indexl():
print(type(jsonify({"username": "lisi"}))) # <class 'flask.wrappers.Response'>
return jsonify({"username": "lisi"}), '203 OK', {'Server':'nginx'}
5. 响应中文
- json.dumps(dict,
ensure_ascii=False
) : 支持中文格式
@app.route('/')
def index():
# return json.dumps({"username": "张三"}) # {"username": "\u5f20\u4e09"}
return json.dumps({"username": "张三"}, ensure_ascii=False) # {"username": "张三"}
6. 错误响应和处理
- return
- 单独判断处理,错误返回异常信息
@app.route('/')
def index():
if not request.args.get('username'):
return make_response('没有授权','401 ERROR')
return request.args.get('username')
- abort
- abort()或raise()抛出异常,并使用
@app.errorhandler(code)
统一拦截处理- 建议使用此方式,符合python 1个函数只有1个return的哲学
# 自定义401错误响应页面,配合abort使用
@app.errorhandler(401)
def error_401(error):
return render_template("error_401.html")
@app.route('/')
def index():
if not request.args.get('username'):
abort(401)
return 'success'
class LoginException(Exception):
pass
# 自定义401错误响应页面,配合abort使用
@app.errorhandler(LoginException)
def error_401(error):
return json.dumps({'msg': str(error)})
@app.route('/')
def index():
if not request.args.get('username'):
raise LoginException('not login')
return 'success'
- 全局错误处理
# 404全局错误封装
@app.errorhandler(404)
def page_not_fonud(error):
# return json.dumps({'msg': "系统正在升级,请耐心等待"},ensure_ascii=False), 404
return render_template('404.html'), 404
参考文档
- https://www.cnblogs.com/jiangmingbai/p/13179950.html