getlist 如何处理多值
如果我们请求 http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,仔细看下,app有两个值。
如果我们的代码是:
from flask import Flask, request app = Flask(__name__) @app.route('/') def hello_world(): r = request.args.get('app') return r if __name__ == '__main__': app.run(port=5000, debug=True)
在浏览器中请求时,我们只会看到 ios。
我们可以使用getlist获取所有的app的值
from flask import Flask, request app = Flask(__name__) @app.route('/') def hello_world(): r = request.args.getlist('app') # 返回一个list return str(r) if __name__ == '__main__': app.run(port=5000, debug=True)
浏览器输入 http://127.0.0.1:5000/?name=Loen&age&app=ios&app=android,我们会看到['ios', 'android']
。
获取POST方法传送的数据
作为一种HTTP请求方法,POST用于向指定的资源提交要被处理的数据。
比如: 我们在某网站注册用户、写文章等时候,需要将数据传递到网站服务器中。并不适合将数据放到URL参数中,密码放到URL参数中容易被看到,文章数据又太多,浏览器不一定支持太长长度的URL。这时,一般使用POST方法。
本课程使用python的requests库模拟浏览器。
安装方法:
pip install requests
看POST数据内容
以用户注册为例子,我们需要向服务器/register传送用户名name和密码password。如下编写server.py。
from flask import Flask, request app = Flask(__name__) @app.route('/register', methods=['POST']) def register(): print(request.headers) print(request.stream.read()) return 'welcome' if __name__ == '__main__': app.run(port=5000, debug=True)
@app.route('/register', methods=['POST'])
是指url/register
只接受POST方法。可以根据需要修改methods参数,例如如果想要让它同时支持GET和POST,这样写:
@app.route('/register', methods=['GET', 'POST'])
浏览器模拟工具client.py
内容如下:
import requests user_info = {'name': 'Loen', 'password': 'loveyou'} r = requests.post("http://127.0.0.1:5000/register", data=user_info) print(r.text)
运行server.py
,然后运行client.py
。client.py
将输出:
welcome
而server.py在终端中输出以下调试信息(通过print输出):
前6行是client.py生成的HTTP请求头,由print(request.headers)输出。
请求体的数据,我们通过print(request.stream.read())输出,结果是:
b'name=Loen&password=loveyou'
解析POST数据
上面,我们看到post的数据内容是:
b'name=Loen&password=loveyou'
我们要想办法把我们要的name、password提取出来,怎么做呢?
Flask已经内置了解析器request.form。
我们将服务代码改成:
from flask import Flask, request app = Flask(__name__) @app.route('/register', methods=['POST']) def register(): print(request.headers) # print(request.stream.read()) # 不要用,否则下面的form取不到数据 print(request.form) print(request.form['name']) print(request.form.get('name')) print(request.form.getlist('name')) print(request.form.get('nickname', default='little apple')) return 'welcome' if __name__ == '__main__': app.run(port=5000, debug=True)
执行client.py
请求数据,服务器代码会在终端输出:
request.form会自动解析数据。
request.form['name']和request.form.get('name')都可以获取name对应的值。对于request.form.get()可以为参数default指定值以作为默认值。所以:
print(request.form.get('nickname', default='little apple'))
输出的是默认值
little apple
获取POST中的列表数据
如果name
有多个值,可以使用request.form.getlist('name')
,该方法将返回一个列表。我们将client.py改一下:
import requests user_info = {'name': ['Loen', 'Alan'], 'password': 'loveyou'} r = requests.post("http://127.0.0.1:5000/register", data=user_info) print(r.text)
此时运行client.py
,print(request.form.getlist('name'))
将输出:
[u'Loen', u'Alan']
处理和响应JSON数据
使用 HTTP POST 方法传到网站服务器的数据格式可以有很多种,比如「获取POST方法传送的数据」课程中讲到的name=Loen&password=loveyou这种用过&符号分割的key-value键值对格式。我们也可以用JSON格式、XML格式。相比XML的重量、规范繁琐,JSON显得非常小巧和易用。
如果POST的数据是JSON格式,request.json会自动将json数据转换成Python类型(字典或者列表)。
编写server.py:
from flask import Flask, request app = Flask("myapp") @app.route('/add', methods=['POST']) def add(): print(request.headers) print(type(request.json)) print(request.json) result = request.json['n1'] + request.json['n2'] return str(result) if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
编写client.py
模拟浏览器请求:
import requests json_data = {'n1': 5, 'n2': 3} r = requests.post("http://127.0.0.1:5000/add", json=json_data) print(r.text)
运行server.py,然后运行client.py,client.py 会在终端输出:
注意,请求头中Content-Type
的值是application/json
。
响应JSON
响应JSON时,除了要把响应体改成JSON格式,响应头的Content-Type也要设置为application/json。
编写server.py:
from flask import Flask, request, Response import json app = Flask("myapp") @app.route('/add', methods=['POST']) def add(): result = {'sum': request.json['n1'] + request.json['n2']} return Response(json.dumps(result), mimetype='application/json') if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
修改后运行。
编写client.py:
import requests json_data = {'n1': 5, 'n2': 3} r = requests.post("http://127.0.0.1:5000/add", json=json_data) print(r.headers) print(r.text)
运行client.py
,将显示:
client终端返回的第一段内容是服务器的响应头,第二段内容是响应体,也就是服务器返回的JSON格式数据。
另外,如果需要服务器的HTTP响应头具有更好的可定制性,比如自定义Server,可以如下修改add()函数:
@app.route('/add', methods=['POST']) def add(): result = {'sum': request.json['n1'] + request.json['n2']} resp = Response(json.dumps(result), mimetype='application/json') resp.headers.add('Server', 'python flask') return resp
client.py
运行后会输出:
{'Content-Type': 'application/json', 'Content-Length': '10', 'Server': 'python flask', 'Date': 'Wed, 11 Sep 2019 09:09:18 GMT'} {"sum": 8}
响应JSON
使用 jsonify 工具函数。
from flask import Flask, request, jsonify app = Flask("myapp") @app.route('/add', methods=['POST']) def add(): result = {'sum': request.json['n1'] + request.json['n2']} return jsonify(result) if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
运行结果: