Flask是一个轻量级的web开发框架,依赖jinja2和Werkzeug WSGI服务的一个微型框架。
官方文档:https://flask.palletsprojects.com/en/2.0.x/
中文文档:http://docs.jinkan.org/docs/flask/
中文文档的版本会比较低,如果英语OK的话,可以看官方文档。
使用pip命令安装:pip install flask
新建一个py脚本,这里是flask_hello.py脚本,脚本内容如下:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "Hello World!
"
脚本中,需要导入Flask类,并创建Flask对象app,然后使用app.route()装饰器设置hello_world()的路由(即接口路径)。
脚本编辑好之后,启动该脚本的flask服务,切换到脚本所在目录,执行flask run命令:flask --app flask_hello run
(flask_hello为脚本名称)
启动flask服务的命令,不同的flask版本不太一样,我这里是2.2.2版本的,如果想知道其他的版本的,可以去官网选择对应版本查看
启动flask服务还有另一个方法,就是在脚本里写上启动代码:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "Hello World!
--python命令启动"
if __name__=="__main__":
# 启动flask服务
app.run()
我们访问http或https链接(即url)的时候,是有接口路径,在flask服务中,可以根据接口路径确定是哪个程序处理该请求。路由有静态路由和动态路由。设置路由的方式是先定义一个Flask对象,然后根据Flask对象中的route(rule: str, **options: t.Any)
定义路由
静态路由即路径是固定的,没有变动的,如入门的例子中,@app.route("/")
就是静态的根路由。
示例如下:
py脚本内容定义如下:
from flask import Flask
app = Flask(__name__)
@app.route("/search/video")
def search_videos():
return "查找视频资源"
@app.route("/search/picture")
def search_pictures():
return "查找图片资源"
if __name__=="__main__":
app.run()
其中,/search/video
和/search/picture
是定义的静态路由,访问时的接口路径无变动
有时候,接口路径是变动的,比如查询用户信息,查询用户A、用户B、用户C,并且用户信息不可控,不能每一个用户都造个路由,flask提供了动态路由,将变动的信息定义为一个变量。
添加路由时,将变动的部分使用<变量名>
定义,然后被装饰的函数或方法,参数的名称与定义的变量名一致,这样函数或方法就可以使用该变量及其值。
示例:
from flask import Flask
app = Flask(__name__)
@app.route("/userinfo//info" )
def search_videos(user_id):
return f"这个是{user_id}的用户信息"
if __name__=="__main__":
app.run()
执行脚本,启动flask服务后,访问如下:
从结果中可以看出,/userinfo/后/info前的内容可以变动,也能处理成功。
动态路由中,可以给变量限制其数据类型,格式:<类型:变量名>
数据类型有如下:
类型 | 描述 |
---|---|
string | (缺省值)接受任何不包含斜杠的文本 |
int | 接受正整数 |
float | 接受正浮点数 |
path | 类似string,但可以包含斜杠 |
uuid | 接受UUID字符串 |
示例:
from flask import Flask
app = Flask(__name__)
@app.route("/userinfo//info" )
def search_videos(user_id):
return f"用户编号{user_id}的信息如下:巴拉巴拉巴拉。。。"
if __name__=="__main__":
app.run()
在动态路由中的变量的数据类型限制比较简单,如果是复杂的校验,则可以在函数内部进行校验。
/
有时候我们在接口路径末尾加/
和不加/
的时候,访问是一致的,但有些加了/
访问又报错,flask对路由尾部的/
是有做处理的:
/
:访问时加/
和不加/
效果是一样的/
:访问时不加/
会报错,只能加/
才能访问成功示例如下:
from flask import Flask
app = Flask(__name__)
@app.route("/add1/")
def add1():
return f"路由的末尾有'/'"
@app.route("/add2")
def add2():
return f"路由的末尾没有'/'"
if __name__=="__main__":
app.run()
请求方式有GET、POST、PUT等等,常用的有GET和POST,我们可以在Flask()对象设置路由时传入methods
参数来设置路由的请求方式,格式:@Flask().route(rule, methods=["GET", xxx, xxx])
脚本内容如下:
from flask import Flask
app = Flask(__name__)
@app.route("/get_demo/info", methods=["GET"])
def only_get():
return "只支持get请求方式"
@app.route("/post_and_get_demo/info", methods=["GET", "POST"])
def both_post_get():
return "支持get和post的请求方式"
if __name__=="__main__":
app.run()
发送请求的时候,必定会接触到上传的参数,然后根据上传的参数进行逻辑处理。那我们怎么获取请求上传的数据呢?flask框架提供了request类,可以通过该类获取对应的请求数据。
属性/方法 | 说明 |
---|---|
args | 记录了请求中的查询参数,返回类似于字典的数据 |
json | 记录了请求中的json数据(dict类型) |
files | 记录了请求上传的文件,返回类似于字典的数据 |
form | 记录了请求中的表单数据,返回类似于字典的数据 |
method | 记录了请求使用的HTTP方法 |
url | 记录了请求中的URL地址 |
host | 记录了请求的域名 |
headers | 记录了请求的请求头信息,返回类似于字典的数据 |
示例:
from flask import Flask, request
wen = Flask(__name__)
@wen.route("/request/info", methods=["GET"])
def get_request_info():
print(f"request.args类型:{type(request.args)}")
print(f"request.args = {request.args}\n")
print(f"request.json类型:{type(request.json)}")
print(f"request.json = {request.json}\n")
print(f"request.files类型:{type(request.files)}")
print(f"request.files = {request.files}\n")
print(f"request.form类型:{type(request.form)}")
print(f"request.form = {request.form}\n")
print(f"request.method类型:{type(request.method)}")
print(f"request.method = {request.method}\n")
print(f"request.url类型:{type(request.url)}")
print(f"request.url = {request.url}\n")
print(f"request.host类型:{type(request.host)}")
print(f"request.host = {request.host}\n")
print(f"request.headers类型:{type(request.headers)}")
print(f"request.headers = {request.headers}\n")
return {"status": 0, "message": "get success"}
if __name__ == "__main__":
wen.run()
执行python脚本(即启动flask服务),发送请求
控制台输出如下:
url链接中,有时会有请求参数,我们可以通过flask.request下的args属性获取到请求参数
示例:
from flask import Flask, request
wen = Flask(__name__)
@wen.route("/get/info", methods=["GET", "POST"])
def get_request_info():
data = {}
data.update(request.args)
print(data)
return data
if __name__ == "__main__":
wen.run()
发送请求时,有时请求体数据是json数据,flask可以通过flask.request下的json属性获取到json请求体数据
脚本内容如下:
from flask import Flask, request
app = Flask(__name__)
@app.route("/post/info", methods=[ "POST"])
def post_json_data():
print(f"请求json报文:{request.json}")
return {"code": 0, "body_data": request.json}
if __name__ == "__main__":
app.run()
发送请求时,有时请求体数据是json数据,flask可以通过flask.request下的form属性获取到form表单数据
脚本内容如下:
from flask import Flask, request
app = Flask(__name__)
@app.route("/form/info", methods=[ "POST"])
def post_form_data():
print(f"form数据:{request.form}")
return {"code": 0, "form_data": request.form}
if __name__ == "__main__":
app.run()
有些请求是上传文件,flask可以通过flask.request下的files属性获取到上传的文件数据。
request.files
:返回类似一个字典类型的数据,包含了所有上传的文件对象FileStorage,可以通过get(“xxx”)获取到具体的文件对象,如request.files.get("data")
表示获取参数是data的文件对象文件对象FileStorage有多个方法支持操作,常用的有:
属性/方法 | 说明 |
---|---|
filename | 文件名称 |
stream | 文件流对象 |
save(dst, buffer_size=16384) | 将文件对象的内容保存到指定路径dst |
脚本内容如下:
from flask import Flask, request
app = Flask(__name__)
@app.route("/form/info", methods=[ "POST"])
def post_form_data():
print(f"files数据:{request.files}")
fo = request.files.get("data")
for data in fo.stream:
print(data.decode("utf-8"), end="")
return {"code": 0, "file_name": fo.filename}
if __name__ == "__main__":
app.run()
执行脚本(启动flask服务),发送文件上传的请求
控制台输出内容为:
返回的响应报文有多种格式,比如文本、json、html等。
响应报文如果是文本内容时,直接在函数内return字符串内容,flask会封装成文本格式的响应报文
示例:
from flask import Flask
app = Flask(__name__)
@app.route("/text", methods=[ "POST"])
def text_resp():
return "响应报文内容是文本内容"
if __name__ == "__main__":
app.run()
执行脚本后,postman发送请求如下:
从响应报文中可以看到响应头的Content-Type是text/html,响应报文体是个文本内容
除了设置响应报文体外,我们还可以返回元组,元组必须包含报文体,可以包含响应状态码和响应头,返回的元组设置如下:
响应状态码status默认为200,headers会根据response进行简单的调整。
示例:
from flask import Flask
app = Flask(__name__)
@app.route("/demo1", methods=[ "POST"])
def response_status():
return "响应报文内容是文本内容", 201
@app.route("/demo2", methods=[ "POST"])
def resp_json_status():
return {"name": "wenxiaoba", "age": 18}, 201
@app.route("/demo3", methods=[ "POST"])
def resp_headers():
return "设置了响应报文和响应头", {"token": "123456abcde", "address": "where are you"}
@app.route("/demo4", methods=[ "POST"])
def resp_status_headers():
return "设置了响应报文和响应头", 202, {"token": "123456abcde", "address": "where are you"}
if __name__ == "__main__":
app.run()
执行脚本(启动flask服务),发送请求,相关内容如下:
请求/demo1时,可以看到响应报文体和响应状态码是设置的内容
请求/demo2时,响应报文体是json格式的
请求/demo3时,返回了设置的响应报文体,响应状态码是flask默认的200,响应头也有包含设置的字段
请求/demo4时,返回的响应报文体、状态码均为设置的,响应头也包含了设置的字段
大多数接口返回的响应数据是json格式,flask框架中,有2种方式返回json格式的响应报文:
返回dict(即字典)数据时,客户端实际接收到的是json数据
/jsonify1接口是通过jsonify()传入字典参数处理的响应报文
/jsonify2接口是通过jsonify()传入键值对参数处理的响应报文
除了经常用的json和文本格式外,还会返回其他格式,比如html、xml等,我们可以使用render_template()函数进行处理。
使用render_template()函数需要先导入flask.render_template,函数如下:
render_template(template_name_or_list, **context)
templates
目录下{{变量名}}
),可以通过这个参数传入,传入键值对,如:变量名=值py脚本内容如下:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/gethtml", methods=["POST"])
def get_html():
return render_template('demo.html', name="wenxiaoba")
@app.route("/getxml", methods=["POST"])
def get_xml():
# 由于返回的是xml数据,所以需要设置响应头的content-type内容,说明传输的是xml数据,否则会被当成html数据
return render_template('data.xml', book_name="随便起的书名"), {"content-type": "application/xml"}
if __name__ == "__main__":
app.run()
在脚本同一目录下,创建templates目录,在templates目录下创建demo.html、data.xml文件。
demo.html的内容如下:
<html>
<body>
<h1>{{name}}的博客h1>
<p>这是一个非常勤奋的娃,她想做测试开发,赚更多的钱p>
body>
html>
data.xml的内容如下:
<book>
<body>
<book_name>python简明教程book_name>
<author>谁谁谁author>
<price>56price>
body>
<body>
<book_name>{{book_name}}book_name>
<author>不知道author>
<price>62.3price>
body>
book>
如果想设置更多的响应信息,比如cookie,可以通过make_response()
获取一个响应对象,可以在该对象中设置cookie、请求头等内容。
示例:
py脚本内容如下:
from flask import Flask, request, make_response, render_template
app = Flask(__name__)
@app.route("/setcookie", methods=["POST"])
def set_cookie():
type = request.json.get("type")
if "html" == type: # 如果请求上传的json中,type为html时,返回html内容
resp = make_response(render_template("demo.html", name="wenxiaoba"))
else:
dict_data = {
"name": "wenxiaoba",
"age": 32,
"gender": True
}
resp = make_response(dict_data)
# 设置cookie,
resp.set_cookie("cookie1", "cookie1_value")
resp.set_cookie("cookie2", "cookie2 value")
# 设置响应头
resp.headers["test"] = "test headers value"
return resp
if __name__ == "__main__":
app.run()
在前面例子中,我们基本上是通过脚本执行run()方法来启动flask服务,run()方法可以传入多个参数,对服务内容进行配置,但是我们均未设置参数,现在来说下比较常用的参数。
run()方法:run(host, port, debug, load_dotenv=True, **options)
示例:
py脚本内容为:
from flask import Flask
app = Flask(__name__)
@app.route("/demo", methods=["POST"])
def demo():
return "content data text"
if __name__ == "__main__":
app.run(host="192.168.1.105", port=8888, debug=True)
执行脚本(即启动flask服务)后,从控制台日志可以看到,现在的flask服务在192.168.1.105的8888端口进行监听(当然flask服务也部署在192.168.1.105设备上),而且也提示了Debugger模式在生效中
我们发送请求到8888端口
当我们对py脚本进行修改,并保存,保存的时候可以看到控制台重新加载了flask服务,这就是debug模式的优势,脚本编辑了之后,不用手动重新启动flask,只需要保存就会重新加载flask服务。
一般接口使用的规范是RESTFul风格规范(我也不太清楚),flask-restx是一个支持RESTFul的flask插件,用于规范化接口的编写,并且支持swagger文档
官方说明:https://github.com/python-restx/flask-restx
官方文档:https://flask-restx.readthedocs.io/en/latest/
安装:pip install flask-restx
我们按照官方的示例来入门,官方脚本如下:
from flask import Flask
from flask_restx import Resource, Api
# 创建Flask对象app
app = Flask(__name__)
# 创建Api对象api,创建时,将Flask对象app作为参数传入
api = Api(app)
# 使用Api对象api来添加路由(不使用Flask对象app来添加路由)
# 至于methods,不在添加路由时限制,在装饰的类方法中限制
@api.route('/hello')
class HelloWorld(Resource): # 创建HelloWorld类,必须继承Resource模块
def get(self): # 定义RESTFul风格的get方法(对应get请求方式)
return {'hello': 'world'}
if __name__ == '__main__':
app.run(debug=True)
执行脚本(启动flask服务),发送请求,结果如下:
根据示例中的注释,如果我们想定义一个接口,支持get和post的请求方式,则需要在对应的类中定义get()和post()方法,简单示例如下:
py脚本内容如下:
from flask import Flask, request
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
@api.route("/person/info")
class Person(Resource):
def get(self):
return "get方法不安全,没有权限查看个人信息"
def post(self):
name = request.json.get("name")
return {"name": name, "age": 27, "gender": True}
if __name__=="__main__":
app.run()
执行py脚本(启动flask服务)后,发送请求,结果如下:
get请求:
post请求:
如果请求方式非get或post,则报错
从 简单入门 的示例中,我们知道了怎么添加路由,其实flask_restx插件还提供了add_resource()方法来添加路由。即flask_restx插件有2种方法来添加路由:
route()可以一次性添加多个路由,示例如下:
py脚本内容如下:
from flask import Flask, request
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
@api.route("/path1/demo", "/path2/demo", "/path3/demo")
class demo(Resource):
def post(self):
return f"接口路径是:{request.path}"
if __name__=="__main__":
app.run()
add_resource()是给指定的类添加路由,示例如下:
py脚本内容如下:
from flask import Flask, request
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
class Demo(Resource):
def post(self, name):
return {"path": request.path, "name": name}
# 给Demo类添加路由
api.add_resource(Demo, '/demo1/' , '/demo2//info' )
if __name__=="__main__":
app.run()
在设计框架的时候,一般遵循复用性、高内聚、低耦合
,即容易维护,减少冗余。
高耦合:可以理解为程序非常复杂难以维护,若修改了程序的某一处内容,涉及到方方面面(其他功能)都要跟着改,比如一个程序有100个函数执行正常,然而修改了其中1个函数,其他99个函数都要跟着修改,就是高耦合的场景。低耦合要求将完整的流程拆分成几个独立的模块、独立的功能,模块内的修改不影响模块之间的交互逻辑,比如商户订单管理和用户订单支付都是不同的模块,修改了商户订单管理的某个功能后,用户订单支付的大部分功能不需要修改。
from flask import Flask, request
app = Flask(__name__)
@app.route("/demo", methods=["GET", "POST", "PUT", "DELETE"])
def demo():
if request.method == "GET":
return "获取订单"
elif request.method == "POST":
return "生成订单"
elif request.method == "PUT":
return "修改订单"
else:
return "删除订单"
该示例中,将订单的增删改查都在一个函数里完成,如果突然某天需要增加审批订单的功能,其他订单功能都受影响,就需要阅读一大坨代码,然后又是增加代码,又是修改代码的,都在一个函数下,非常不美观(一看到这么多代码,会比较泄气),也不好维护。
from flask import Flask
app = Flask(__name__)
@app.route("/order", methods=["GET"])
def query_order():
return "查询订单"
@app.route("/order", methods=["POST"])
def create_order():
return "生成订单"
@app.route("/order", methods=["PUT"])
def modify_order():
return "修改订单"
@app.route("/order", methods=["DELETE"])
def delete_order():
return "删除订单"
@app.route("/approval", methods=["POST"])
def approvaled():
return "审批通过"
@app.route("/approval", methods=["DELETE"])
def reject():
return "审批驳回"
该示例中,有/order接口的不同请求方法,有/approval接口的不同请求方法,总之,都是一个接口路径对应多个请求方法。在该示例中,代码没有复用性,维护起来比较杂乱,包含了操作人员的订单管理(增删改查)、审批人员的订单管理(审批通过、审批驳回),归纳起来,可以分为2个维度:操作人员的订单管理、订单的审批流程。如果一个模块有很多个功能,有许多个维度,则维护成本也是逐渐增加,且不易分辨,需要去看注释或代码来确定当前函数的处理内容。
设计过程中需要遵循复用性、高内聚、低耦合
,RESTFul风格规范会根据请求方式来设计不同的逻辑。
请求方式 | 说明 |
---|---|
GET | 获取服务器资源 |
POST | 新增服务器资源 |
PUT | 更新服务器资源(客户端提供改变后的完整资源) |
DELETE | 删除服务器资源 |
示例:
from flask import Flask
from flask_restx import Api, Resource
app = Flask(__name__)
api = Api(app)
@api.route("/order")
class OrderOpt(Resource):
def get(self):
return "查询订单"
def post(self):
return "生成订单"
def put(self):
return "修改订单"
def delete(self):
return "删除订单"
@api.route("/approval")
class ApprovalProcess(Resource):
def post(self):
return "审批通过"
def delete(self):
return "审批驳回"
在该示例中,从2个维度去维护订单功能:操作人员的订单管理、订单的审批流程,虽然订单管理和审批流程之间可能会有影响,但从一定程度上降低了高耦合,另一方面也更好的进行维护管理。
一般而言,开发在设计、开发接口的时候,需要提供接口文档给到其他开发进行联调,或给到测试进行接口测试。flask-restx插件集成了swagger,可以对接口进行模块管理,也可对接口文档进行配置。
flask-restx插件集成swagger,依赖于namespace的使用。
在 RESTFul风格示例 的示例中,如果我们访问接口根路径,发现界面如下:
从图中可以看出,接口都在default namespace下,如果接口很多的话,就不利于管理,flask-restx插件的namespace可以对接口进行分类管理。
使用namespace进行接口分类管理,需要进行如下步骤:
使用到的类或方法说明如下:
Namespace类:
- 定义对象:
Namespace(name, description=None, path=None, decorators=None, validate=None, authorizations=None, ordered=False, **kwargs)
- 参数说明:
- name:分类名称
- description:分类描述
- path:前置路径(后面会根据步骤2的装饰器和步骤3的路径设置决定接口的完整路径)
@Namespace().route(“”)是将类归纳到某个Namespace对象下,即将类对应的接口归纳到某个层级下,route()可以设置子路由,受步骤1中Namespace的path参数和步骤3的add_namespace()方法影响,
如果不设置子路由,则传入空字符串(不要什么都不传)
Api对象的
add_namespace(ns, path=None)
是将对应的Namespace对象ns添加到flask服务中(如果不加则识别不到对应类的接口),并设置前置路径path。
关于namespace的接口分类管理,我们从步骤1到步骤3可以看到,有3个地方设置路由,分别是Namespace实例化时的参数path、装饰器Namespace对象的route()方法、Api对象的add_namespace()方法中的path参数,关于这3个地方对对应接口的接口路径的最终结果,如下:
示例:
py脚本内容如下:
from flask import Flask
from flask_restx import Api, Resource, Namespace
app = Flask(__name__)
api = Api(app)
# 定义Namespace实例
ns1 = Namespace("demo management", "add_namespace()和Namespace()都有path参数传入", path="/name1")
ns2 = Namespace("demo2 management", "add_namespace()无path参数传入,Namespace()有path参数传入", path="/name2")
ns3 = Namespace("demo3 management", "add_namespace()和Namespace()都无path参数传入")
ns4 = Namespace("demo4 management", "add_namespace()和Namespace()都有path参数传入,route()传入空字符串", path="/name4")
ns5 = Namespace("demo5 management", "add_namespace()和Namespace()都有path参数传入,route()未传参", path="/name5")
@ns1.route("/route1")
class Demo1(Resource):
def get(self):
return "demo1 get"
def post(self):
return "demo1 post"
@ns2.route("/route2")
class Demo2(Resource):
def get(self):
return "demo2 get"
def post(self):
return "demo2 post"
@ns3.route("/route3")
class Demo3(Resource):
def get(self):
return "demo3 get"
@ns4.route("")
class Demo4(Resource):
def get(self):
return "demo4 get"
@ns5.route()
class Demo5(Resource):
def get(self):
return "demo5 get"
api.add_namespace(ns1, "/api_add")
api.add_namespace(ns2)
api.add_namespace(ns3)
api.add_namespace(ns4, "/api_add4")
api.add_namespace(ns5, "/api_add5")
if __name__=="__main__":
app.run()
flask-rest中swagger文档配置有2种方式:
@Api对象.doc()
或者@namespace对象.doc()
装饰请求方法parser = api.parser()
配合`@api.expect(parser)装饰器入参的校验和传入推荐使用第二种方式
py脚本内容是:
from flask import Flask, request
from flask_restx import Api, Resource, Namespace, fields
app = Flask(__name__)
api = Api(app)
ns = Namespace("分类名称", description="分类的描述")
@ns.route("")
class Demo(Resource):
# doc()种对请求参数params(即url参数)进行字段说明
@ns.doc(params={"id": "用户编号", "subject": "科目"})
def get(self):
return {"code": 0, "data": request.args}
#
post_check_model = api.model("PostModel", {
"name": fields.String(description="姓名", required=True),
"age": fields.Integer(min=0),
"gender": fields.String(description="性别", enum=["男", "女"])
})
@ns.doc(body=post_check_model)
def post(self):
data = request.json
return f"{data.get('name')}, {data.get('age')}岁, {data.get('gender')}性"
api.add_namespace(ns, "/demo")
if __name__=="__main__":
app.run(debug=True)
doc()的方式相当于对接口字段进行了描述,并没有很好的对接口字段进行限制,所以不推荐这种方式。
比较推荐的swagger接口文档配置步骤如下:
parser()
方法获取RequestParser对象add_argument()
方法对接口请求字段进行设置expect()
方法将RequestParser对象传入,表明该接口使用该RequestParser对象的接口字段定义。RequestParser对象的add_argument(*args, **kwargs)
方法是对接口请求字段进行配置,相关的关键参数说明如下:
示例:
from flask import Flask, request
from flask_restx import Api, Resource, Namespace
from werkzeug.datastructures import FileStorage
app = Flask(__name__)
api = Api(app)
ns = Namespace("分类名称", description="分类的描述")
@ns.route("")
class Demo(Resource):
# 定义RequestParser解析器对象
get_parser = api.parser()
# 通过RequestParser对象添加接口请求字段参数配置
get_parser.add_argument("id", type=int, help="身份证号", location="args")
get_parser.add_argument("subject", type=str, help="科目", location="args")
# 通过Namespace对象的expect(RequestParser对象)方法,对get请求进行装饰(即对该get请求接口字段指定字段配置
@ns.expect(get_parser)
def get(self):
return {"code": 0, "args_data": request.args}
post_parser = api.parser()
post_parser.add_argument("file_data", type=FileStorage, help="上传文件", location="files")
post_parser.add_argument("account", type=str, help="帐号", location="form")
post_parser.add_argument("password", help="密码", location="form")
@ns.expect(post_parser)
def post(self):
return {"status_code": "success", "form_data": request.form, "file_name": request.files.get("file_data").filename}
put_parser = api.parser()
put_parser.add_argument("name", type=str, help="姓名", location="json", required=True)
put_parser.add_argument("age", type=int, help="年龄", location="json")
put_parser.add_argument("gender", help="性别", choices=["男", "女"], location="json")
@ns.expect(put_parser)
def put(self):
return {"code": 0, "message": "success", "json_data": request.json}
api.add_namespace(ns, "/demo")
if __name__=="__main__":
app.run(debug=True)
执行脚本(启动flask服务),访问根目录并发送请求,结果如下:
注意:Swagger 的检验比较虚(即字段校验一般不生效),真要强制约束请求信息,还是要在代码里