在视图编写中需要读取客户端请求携带的数据时,如何才能正确的取出数据呢?请求携带的数据可能出现在HTTP报文中的不同位置,需要使用不同的方法来获取参数。
1、获取url路径上的数据示例代码:
from flask import Flask, jsonify
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
books = [
{"id": 1, "name": '三国演义'},
{"id": 2, "name": '水浒传'},
{"id": 3, "name": '西游记'},
{"id": 4, "name": '红楼梦'},
]
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/books/list')
def book_list():
# return books # 直接返回books会报错的,类型格式不支持
return jsonify(books)
if __name__ == '__main__':
app.run()
运行结果:
示例代码:
from flask import Flask, jsonify
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
books = [
{"id": 1, "name": '三国演义'},
{"id": 2, "name": '水浒传'},
{"id": 3, "name": '西游记'},
{"id": 4, "name": '红楼梦'},
]
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/books/list')
def book_list():
# return books # 直接返回books会报错的,类型格式不支持
return jsonify(books)
@app.route('/book/')
def book_detail(book_id):
for book in books:
if book_id == book['id']:
return book
return f"id:{book_id}的图书不存在!"
if __name__ == '__main__':
app.run()
运行结果:
例如,有一个请求访问的接口地址为/users/123
,其中123实际上为具体的请求参数,表明请求123号用户的信息。此时如何从url中提取出123的数据?
Flask不同于Django直接在定义路由时编写正则表达式的方式,而是采用转换器语法:
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
示例代码:
from flask import Flask
app = Flask(__name__)
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
if __name__ == '__main__':
app.run()
运行效果:
此处的即是一个转换器,默认为字符串类型,即将该位置的数据以字符串格式进行匹配、并以字符串为数据类型类型、
user_id
为参数名传入视图。
,尖括号是固定写法,语法为,variable默认的数据类型是字符串。如果需要指定类型,则要写成,其中converter就是类型名称,可以有以下几种:
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
- string: 默认的数据类型,接受没有任何斜杠/的字符串。
- int: 整形
- float: 浮点型。
- path: 和string类似,但是可以传递斜杠/。
- uuid: uuid类型的字符串。
- any:可以指定多种路径。
将上面的例子以整型匹配数据,可以如下使用:
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
示例代码1:
from flask import Flask
app = Flask(__name__)
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
if __name__ == '__main__':
app.run()
运行效果:
示例代码2:
from flask import Flask
app = Flask(__name__)
@app.route('/users/')
def user_info(user_id):
print(type(user_id))
return 'hello user {}'.format(user_id)
if __name__ == '__main__':
app.run()
运行效果:

如果遇到需要匹配提取/sms_codes/18512345678
中的手机号数据,Flask内置的转换器就无法满足需求,此时需要自定义转换器。
自定义转换器主要做3步
-
创建转换器类,保存匹配时的正则表达式
from werkzeug.routing import BaseConverter class MobileConverter(BaseConverter): """ 手机号格式 """ regex = r'1[3-9]\d{9}'
- 注意
regex
名字固定
- 注意
-
将自定义的转换器告知Flask应用
app = Flask(__name__) # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile app.url_map.converters['mobile'] = MobileConverter
-
在使用转换器的地方定义使用
@app.route('/sms_codes/') def send_sms_code(mob_num): return 'send sms code to {}'.format(mob_num)
示例代码:
from flask import Flask
from werkzeug.routing import BaseConverter
class MobileConverter(BaseConverter):
"""手机号格式"""
regex = r'1[3-9]\d{9}'
app = Flask(__name__)
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: mobile
app.url_map.converters['mobile'] = MobileConverter
@app.route('/sms_codes/')
def send_code(mob_num):
return 'send sms code to {}'.format(mob_num)
if __name__ == '__main__':
app.run()
运行效果:
any路由示例方法:
from flask import Flask, jsonify
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
@app.route('/')
def hello_world():
return 'hello world'
@app.route('//')
def item(url_path):
return f'I am {url_path}'
if __name__ == '__main__':
app.run()
在上面例子中,item这个函数可以接受两个URL,一个是/article/,另一个是/blog/。注意一定要传url_path参数,当然这个url_path的名称可以随便。
3、 其他参数如果不想定制子路径来传递参数,也可以通过传统的?=的形式来传递参数,例如:/article?id=xxx。如果想要获取其他地方传递的参数,可以通过Flask提供的request对象来读取。
不同位置的参数都存放在request的不同属性中
属性说明类型data记录请求的数据,并转换为字符串*form记录请求中的表单数据MultiDictargs记录请求中的查询参数MultiDictcookies记录请求中的cookie信息Dictheaders记录请求中的报文头EnvironHeadersmethod记录请求使用的HTTP方法GET/POSTurl记录请求的URL地址stringfiles记录请求上传的文件*例如 想要获取请求/articles?channel_id=1
中channel_id
的参数,可以按如下方式使用:
from flask import request
@app.route('/articles')
def get_articles():
channel_id = request.args.get('channel_id')
return 'you wanna get articles of channel {}'.format(channel_id)
示例代码:
from flask import Flask, request
app = Flask(__name__)
@app.route('/articles')
def get_articles():
channel_id = request.args.get('channel_id')
return 'you wanna get articles of channel {}'.format(channel_id)
if __name__ == '__main__':
app.run()
运行效果:
上传图片
客户端上传图片到服务器,并保存到服务器中
from flask import request
@app.route('/upload', methods=['POST'])
def upload_file():
f = request.files['pic']
# with open('./demo.png', 'wb') as new_file:
# new_file.write(f.read())
f.save('./demo.png')
return 'ok'
示例代码:
from flask import Flask, request
app = Flask(__name__)
@app.route('/upload', methods=['POST'])
def upload_file():
f = request.files['pic']
# with open('./demo.png', 'wb') as new_file:
# new_file.write(f.read())
f.save('./demo.png')
return 'ok'
if __name__ == '__main__':
app.run()
【with open 和f.save效果是一样的,f.save是封装好的方法】
postman上传图片测试:
其它参数中分别get()和getlist()方法:
# 源码介绍
def get(self, key, default=None, type=None):
"""Return the default value if the requested data doesn't exist.
If `type` is provided and is a callable it should convert the value,
return it or raise a :exc:`ValueError` if that is not possible. In
this case the function will return the default as if the value was not
found:
>>> d = TypeConversionDict(foo='42', bar='blub')
>>> d.get('foo', type=int)
42
>>> d.get('bar', -1, type=int)
-1
:param key: The key to be looked up.
:param default: The default value to be returned if the key can't
be looked up. If not further specified `None` is
returned.
:param type: A callable that is used to cast the value in the
:class:`MultiDict`. If a :exc:`ValueError` is raised
by this callable the default value is returned.
"""
源码介绍:
def getlist(self, key, type=None):
"""Return the list of items for a given key. If that key is not in the
`MultiDict`, the return value will be an empty list. Just like `get`,
`getlist` accepts a `type` parameter. All items will be converted
with the callable defined there.
:param key: The key to be looked up.
:param type: A callable that is used to cast the value in the
:class:`MultiDict`. If a :exc:`ValueError` is raised
by this callable the value will be removed from the list.
:return: a :class:`list` of all the values for the key.
"""
示例代码:
main.py
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/register', methods=['GET', 'POST']) # 支持get、post请求
def register(): # 视图函数
if request.method == 'GET': # 请求方式是get
return render_template('register.html') # 返回模板
elif request.method == 'POST':
name = request.form.get('name') # form取post方式参数
age = request.form.get('age')
hobby = request.form.getlist('hobby') # getlist取一键多值类型的参数
# hobby = request.form.get('hobby') # get只能获取到多个值中的第一个
return "姓名:%s 年龄:%s 爱好:%s" % (name, age, hobby)
app.config['DEBUG'] = True
if __name__ == '__main__':
# 0.0.0.0代表任何能代表这台机器的地址都可以访问
app.run(host='0.0.0.0', port=5000) # 运行程序
register.html
register
用户名:
年龄:
爱好:吃
喝
玩
乐
运行效果:
参考博文:
Python Flask中Request请求_zhangvalue的博客-CSDN博客_request.form.getlist