1 Flask restful
1.1 简介
flask-restful 是flask扩展包 提供快速工具化构建restful风格api的支持 兼容已有的orm框架
1. 视图类方法映射请求方式(继承Resource视图类 可对多个url进行匹配)
2. 自带参数解析器(数据类型、数据值、其他扩展选项(必选、提示信息、参数类型{query_string|form|json|header}等))
3. 响应数据自定义扩展输出(直接和实体类pv关联、可多重嵌套输出)
1.2 安装
1. 在线
pip install flask-restful
2.离线
git clone https://github.com/twilio/flask-restful.git
cd flask-restful
python setup.py develop
1.3 实例
from flask import Flask
from flask_restful import Api, Resource
class Test(Resource):
def get(self):
return {'data': "data"}
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(Test, '/')
app.run(debug=True)
'''
curl http://localhost:5000/
>>>{"data": "data"}
'''
from flask_cors import CORS
from flask_restful import Api, Resource, reqparse, fields, marshal_with
from flask import Flask
app = Flask(__name__)
CORS(app)
api = Api(app)
todos = {
'todo1': {'task': 1},
'todo2': {'task': 2},
'todo3': {'task': 3},
}
parser = reqparse.RequestParser()
parser.add_argument('task', type=int, help='task-pargrams must be int')
class TodoList(Resource):
def get(self):
return todos, 200, {'Etag': 'some-opaque-string'}
def post(self):
args = parser.parse_args()
todo_id = int(max(todos.keys()).lstrip('todo'))+1
todo_id = 'todo%i' % todo_id
todos[todo_id] = {'task': args['task']}
print(todos[todo_id])
return todos[todo_id], 201
api.add_resource(TodoList, '/todos', '/tasks')
class ToDos(object):
def __init__(self, todo_id, task):
self.todo_id = todo_id
self.task = task
self.status = 'active'
resource_fields = {
'task': fields.String,
'url': fields.Url('todo_ep')
}
class Todo(Resource):
@marshal_with(resource_fields)
def get(self, todo_id):
return ToDos(todo_id=todo_id, task='task'+ str(todo_id)), 200
api.add_resource(Todo, '/todos/<todo_id>', endpoint='todo_ep')
if __name__ == '__main__':
app.run(debug=True)
2 输入(参数解析)
2.1 参数解析器
from flask_restful import reqparse
parser = reqparse.RequestParser()
parser.add_argument('name', type=str, required=True, help='name is not empty', dest='uName', location='')
parser.add_argument('score', type=int, help='score is type:int', action='append')
parser_copy = parser.copy()
PS:
1.实际获取通过校验解析的参数
args = parser.parse_args()
2. 自带参数校验异常响应处理
3. type可以指定特定函数 扩展入参类型(基本数据结构+复杂数据结构)
def num_select(v):
if v % 2 == 0:
return v
else:
raise ValueError(f"value({v}) if invalid")
parser.add_argument("val", type=num_select)
2.2 实例
from flask import Flask, request
from flask_restful import reqparse, Resource, Api
from werkzeug.datastructures import FileStorage
parser = reqparse.RequestParser(trim=True, bundle_errors=True)
'''
-trim: 入参是否去除空格
-bundle_errors: 捆绑输出参数名和参数异常信息
PS: 可全局配置bundle_errors 设置且覆盖所有参数解析器的配置
Flask("myFlask").config['BUNDLE_ERRORS']=True
'''
parser.add_argument('name', type=str, required=True, help='name is not empty', dest='uName', location='args')
parser.add_argument('score', type=int, help='score is type:int', action='append')
parser.add_argument('User-Agent', type=str, location='headers')
parser.add_argument('myCookie', type=str, location='cookies')
parser.add_argument('jsonStr', type=str, location='json')
parser.add_argument('formVal', type=str, location='form')
parser.add_argument('portrait', type=FileStorage, location='files')
'''
add_argument 参数解析
-name: 参数名
-default: 参数默认值
-type: 数据类型
-required: 是否必选
-help: 提示信息
-dest: 入参别名(parse_args()实际存储的参数名)
-ignore: 是否忽略参数类型转换失败(默认为False)
-choices: 参数枚举值(且参数值只能是这些值)
-location: 入参来源(位置)
-form 表单(content-type的值是application/x-www-form-urlencoded 或者 multipart/form-data)
-json json字符串(content-type的值是application/json)
-headers 请求头
-files 文本
-cookies 请求cookies
-args 查询字符串
-values 等价于[form, args]
-action: 参数值操作形式
append 参数值追加
store: 存储值(默认形式)
-case_sensitive: 参数值是否区分大小写(默认True)
-trim: 是否剔除参数名空格(默认False)
-nullable: 是否允许参数值为null(默认为True)
-store_missing: 当获取不到指定参数是否存储默认值(默认为True)
PS: location 可设置多个且优先级最高的是最后一个值(location=[form, json] json优先级高)
'''
parser_copy = parser.copy()
parser_copy.add_argument('bar', type=int)
parser_copy.replace_argument('bar', type=str, required=True)
parser_copy.remove_argument('bar')
class ReqParseTest(Resource):
def get(self):
"""get方法"""
args = parser.parse_args(req=None, strict=False, http_error_code=400)
'''
req: 可根据flask请求上下文覆盖req(默认None)
strict: 实际入参不在参数解析器内部抛出400异常(默认False)
http_error_code: 默认400
'''
print(f"GET-{args}")
print(f"ReqHeaders:\n{request.headers}\n")
return {"data": args, "method": "GET"}, 200
def post(self):
"""post方法"""
args = parser.parse_args()
print(f"POST-{args}")
'''
POST-{'uName': 'fff', 'score': [2, 3], 'User-Agent': 'myHeader', 'myCookie': 'myCookies', 'jsonStr': None, 'formVal': 'formVal', 'portrait': <FileStorage: "'1.jpg'" ('image/jpeg')>}
'''
print(f"ReqHeaders:\n{request.headers}\n")
portrait = args.get("portrait")
if portrait and isinstance(portrait, FileStorage):
args["portrait"] = f"fileSize={len(args.get('portrait').read()) / (1024*1024)}MB"
return {"data": args, "method": "POST"}, 200
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(ReqParseTest, '/')
app.run(debug=True)
# 1. GET请求
curl "http://localhost:5000/?name=fff&score=2&score=3&formVal=formVal&jsonStr=jsonStr&User-Agent:xxx&myCookie:yyy" -H "User-Agent:myHeader" --cookie "myCookie=myCookies"
# 2. POST请求-表单
curl "http://localhost:5000/?name=fff&score=2&score=3" -H "User-Agent:myHeader" --cookie "myCookie=myCookies" -F "portrait=@F:/test/data/1.jpg;filename='1.jpg'" -F "formVal=formVal" -X POST
# 3.POST请求-JSON
curl "http://localhost:5000/?name=fff&score=2&score=3" -H "User-Agent:myHeader" --cookie "myCookie=myCookies" -H "Content-Type:application/json;charset=utf-8;" -d "{\"json_1\": \"json_1\", \"jsonStr\": \"json_2\"}" -X POST


3 输出(响应域)
3.1 响应域
flask-restful 使用fileds模块 对ORM模型类和基本实体类进行映射关联后 达到实际的数据自定义展示渲染输出能够自主控制的目的
import datetime
from flask import Flask
from flask_restful import Resource, fields, marshal_with, marshal, Api
class StuInfo:
def __init__(self, name, class_no, age, admission_time):
self.other_name = name
self.class_no = class_no
self.age = age
self.admission_time = admission_time
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.class_no),
'age': fields.Integer(default=12),
'admission_time': fields.DateTime(dt_format='iso8601'),
}
StuInfo1 = StuInfo("aa", "c1", None, datetime.datetime.now())
class Test1(Resource):
@marshal_with(resource_fields, envelope="result")
def get(self):
return StuInfo1
'''
{
"result": {
"name": "aa",
"cno": "c1",
"age": 12,
"admission_time": "2023-04-03T10:24:55.526729"
}
}
'''
class Test2(Resource):
def get(self):
return marshal(StuInfo1, resource_fields), 200
'''
{
"name": "aa",
"cno": "c1",
"age": 12,
"admission_time": "2023-04-03T10:25:24.180457"
}
'''
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(Test1, '/test1')
api.add_resource(Test2, '/test2')
app.run(debug=True)
3.2 常规用法
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.cno),
'age': fields.Integer(default=12),
'admission_time': fields.DateTime(dt_format='iso8601'),
'score': fields.List(fields.Integer, attribute="score_list"),
'evaluate': Evaluate(attribute="evaluate"),
'school_info': fields.Nested(school_info_resource),
'score_detail': fields.List(fields.Nested(score_detail_resource)),
'api_absolute': fields.Url('hello', absolute=True, scheme='http'),
'api_simple': fields.Url('hello',)
}
school_info_resource = {
"sName": fields.String,
"addr": fields.String
}
resource_fields = {
'school_info': fields.Nested(school_info_resource),
}
class Evaluate(fields.Raw):
def format(self, value):
return "良好" if not value else "优秀"
3.3 实例
import datetime
from flask import Flask
from flask_restful import fields, Resource, marshal_with, Api
class Evaluate(fields.Raw):
def format(self, value):
return "良好" if not value else "优秀"
school_info_resource = {
"sName": fields.String,
"addr": fields.String
}
score_detail_resource = {
"subject": fields.String(attribute=lambda x: x.subject),
"score": fields.Integer
}
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.cno),
'age': fields.Integer(default=12),
'admission_time': fields.DateTime(dt_format='iso8601'),
'score': fields.List(fields.Integer, attribute="score_list"),
'evaluate': Evaluate(attribute="evaluate"),
'school_info': fields.Nested(school_info_resource),
'score_detail': fields.List(fields.Nested(score_detail_resource)),
'api_absolute': fields.Url('hello', absolute=True, scheme='http'),
'api_simple': fields.Url('hello',)
}
class SchoolInfo:
def __init__(self):
self.sName = "学校名"
self.addr = "学校地址"
class ScoreInfo:
def __init__(self):
self.subject = "语文"
self.score = 85
class StuInfo:
def __init__(self, **stu_info):
self.other_name = stu_info.get("name")
self.cno = stu_info.get("cno")
self.age = stu_info.get("age")
self.admission_time = stu_info.get("admission_time")
self.score_list = stu_info.get("score_list")
self.evaluate = stu_info.get("evaluate")
self.school_info = stu_info.get("school_info")
self.score_detail = stu_info.get("score_detail")
class StuResource(Resource):
@marshal_with(resource_fields)
def get(self):
stu_info = {
'name': "n1",
'cno': "c1",
'age': None,
'admission_time': datetime.datetime.now(),
'score_list': [88, 85],
'evaluate': 0,
'school_info': SchoolInfo(),
'score_detail': ScoreInfo()
}
s1 = StuInfo(**stu_info)
return s1
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(StuResource, "/", endpoint='hello')
app.run(debug=True)

4 扩展
4.1 全局响应内容自定义
'''
flask-restful 扩展知识
'''
import json
from flask import Flask, make_response
from flask_restful import fields, Resource, marshal_with, Api
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.cno),
'age': fields.Integer(default=12),
}
class StuInfo:
def __init__(self, **stu_info):
self.other_name = stu_info.get("name")
self.cno = stu_info.get("cno")
self.age = stu_info.get("age")
class StuResource(Resource):
@marshal_with(resource_fields)
def get(self):
stu_info = {
'name': "n1",
'cno': "c1",
'age': None,
}
s1 = StuInfo(**stu_info)
return s1
def out_json(data, code, headers=None):
resp = make_response(json.dumps({"code": 0, "msg": "", "data": data}), code)
resp.headers.extend(headers or {})
return resp
class MyApi(Api):
def __init__(self, *args, **kwargs):
super(MyApi, self).__init__(*args, **kwargs)
self.representations = {
"application/json": out_json,
}
if __name__ == '__main__':
app = Flask(__name__)
api = MyApi(app)
api.add_resource(StuResource, "/", endpoint='hello')
app.run(debug=True)
'''
flask-restful 扩展知识
'''
from functools import wraps
from flask import Flask
from flask_restful import fields, Resource, marshal_with, Api, marshal
common_res = {
"code": fields.Integer(default=0),
"msg": fields.String(default="")
}
def response_return(func):
@wraps(func)
def inner_wraps(*args, **kwargs):
data = func(*args, **kwargs)
data = data if data else None
return_data = marshal(None, common_res)
return_data["data"] = data
return return_data, 200
return inner_wraps
class MyResource(Resource):
method_decorators = [response_return]
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.cno),
'age': fields.Integer(default=12),
}
class StuInfo:
def __init__(self, **stu_info):
self.other_name = stu_info.get("name")
self.cno = stu_info.get("cno")
self.age = stu_info.get("age")
class StuResource(MyResource):
@marshal_with(resource_fields)
def get(self):
stu_info = {
'name': "n1",
'cno': "c1",
'age': None,
}
s1 = StuInfo(**stu_info)
return s1
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(StuResource, "/", endpoint='hello')
app.run(debug=True)

4.2 资源类-装饰器应用
import time
from functools import wraps
from flask import Flask
from flask_restful import marshal_with, fields, marshal, Api, Resource
def cal_time(func):
@wraps(func)
def inner(*args, **kwargs):
st = time.time()
data = func(*args, **kwargs)
data = data if data else {}
time.sleep(0.1)
et = round((time.time() - st), 2)
data.update({'costTime(s)': et, "dataType": str(type(data))})
return data
return inner
def response_return(func):
@wraps(func)
def inner_wraps(*args, **kwargs):
data = func(*args, **kwargs)
data = data if data else None
return_data = marshal(None, {"code": fields.Integer(default=0), "msg": fields.String(default="")})
return_data["data"] = data
return return_data, 200
return inner_wraps
class MyResource(Resource):
method_decorators = [response_return]
resource_fields = {
'name': fields.String(attribute='other_name'),
'cno': fields.String(attribute=lambda x: x.cno),
'age': fields.Integer(default=12),
}
class StuInfo:
def __init__(self, **stu_info):
self.other_name = stu_info.get("name")
self.cno = stu_info.get("cno")
self.age = stu_info.get("age")
class StuResource(MyResource):
method_decorators = {'get': [cal_time]}
@marshal_with(resource_fields)
def get(self):
stu_info = {
'name': "n1",
'cno': "c1",
'age': None,
}
s1 = StuInfo(**stu_info)
return s1
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(StuResource, "/", endpoint='hello')
app.run(debug=True)

4.3 蓝图应用
from flask import Flask, Blueprint
from flask_restful import Api, Resource
class StuResource(Resource):
def get(self):
return "OK"
if __name__ == '__main__':
app = Flask(__name__)
api_bp = Blueprint('api', "api_bp")
api = Api(api_bp)
api.add_resource(StuResource, "/", endpoint='api_bp')
app.register_blueprint(api_bp)
app.run(debug=True)
4.4 资源类引用外部依赖
'''
初始化资源类完成外呼依赖引入
'''
from flask import Flask
from flask_restful import Api, Resource
class StuResource(Resource):
def __init__(self, *args, **kwargs):
self.outside_dependencies = kwargs['od']
def get(self):
return self.outside_dependencies
if __name__ == '__main__':
app = Flask(__name__)
api = Api(app)
api.add_resource(StuResource, "/", endpoint='hello', resource_class_kwargs={"od": "外部依赖引用"})
app.run(debug=True)
5. 参考文档
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构