model()工厂允许您将模型实例化并注册到您的API或Namespace.
有2种使用方式,第一种直接使用 api.model
my_fields = api.model('MyModel', {
'name': fields.String,
'age': fields.Integer(min=0)
})
第二种间接注册到api,以下方式是等价的
# Equivalent to
my_fields = Model('MyModel', {
'name': fields.String,
'age': fields.Integer(min=0)
})
api.models[my_fields.name] = my_fields
user模型
class Users(db.Model):
__tablename__ = 'user' # 数据库表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(128), nullable=False)
is_active = db.Column(db.Boolean, default=1)
email = db.Column(db.String(64), nullable=True)
create_time = db.Column(db.DateTime, default=datetime.now)
update_time = db.Column(db.DateTime, onupdate=datetime.now, default=datetime.now)
def hash_password(self, password):
"""密码加密"""
self.password = sha256_crypt.encrypt(password)
def verify_password(self, password):
"""校验密码"""
return sha256_crypt.verify(password, self.password)
def __repr__(self):
return f"<Users(id='{self.id}', username='{self.username}'...)>"
校验请求入参,除了之前学到的 RequestParser 来定义预期的输入:
@api.route('/api/user', endpoint='user')
class UserView(Resource):
def post(self):
"""add user"""
parser = reqparse.RequestParser()
parser.add_argument('username', required=True, type=str, help='username is required')
parser.add_argument('password', required=True, type=str, help='password is required')
args = parser.parse_args()
print(f'请求参数: {args}')
# 保存数据库
return {"msg": "create success"}
也可以使用api.model() 的方法来校验请求入参, 以下方式是等价的
from flask_restx import Resource, fields
user_input = api.model('UserModel', {
'username': fields.String(required=True),
'password': fields.String(required=True)
})
@api.route('/api/user', endpoint='user')
class UserView(Resource):
@api.expect(user_input, validate=True)
def post(self):
"""add user"""
print(f'请求参数: {api.payload}')
# 保存数据库
return {"msg": "create success"}
装饰器@api.expect()
允许您指定预期的输入字段。它接受一个可选的布尔参数 validate
,指示是否应验证有效payload 参数。
RESTX_VALIDATE可以通过将配置设置为True 或传递validate=True给 API 构造函数来全局自定义验证行为。
以下示例是等效的, 未设置validate=True
功能等价于@api.expect()
功能跟 api.doc()
一样(api.doc()
用于 swagger 文档输出)
使用@api.expect()装饰器:
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
@api.expect(resource_fields)
def get(self):
pass
使用api.doc()装饰器:
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
@api.doc(body=resource_fields)
def get(self):
pass
您可以将列表指定为预期输入:
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
@api.expect([resource_fields])
def get(self):
pass
您可以使用RequestParser来定义预期的输入:
parser = api.parser()
parser.add_argument('param', type=int, help='Some param', location='form')
parser.add_argument('in_files', type=FileStorage, location='files')
@api.route('/with-parser/', endpoint='with-parser')
class WithParserResource(restx.Resource):
@api.expect(parser)
def get(self):
return {}
可以在特定端点上启用或禁用验证:
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
# Payload validation disabled 禁用validate 校验入参
@api.expect(resource_fields)
def post(self):
pass
# Payload validation enabled 启用validate 校验入参
@api.expect(resource_fields, validate=True)
def post(self):
pass
通过配置进行应用程序范围验证的示例:
app.config['RESTX_VALIDATE'] = True
api = Api(app)
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
# Payload validation enabled
@api.expect(resource_fields)
def post(self):
pass
# Payload validation disabled
@api.expect(resource_fields, validate=False)
def post(self):
pass
通过构造函数进行应用程序范围验证的示例:
api = Api(app, validate=True)
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>')
class MyResource(Resource):
# Payload validation enabled
@api.expect(resource_fields)
def post(self):
pass
# Payload validation disabled
@api.expect(resource_fields, validate=False)
def post(self):
pass
这个装饰器像原始marshal_with()装饰器一样工作,不同之处在于它记录了方法。可选参数code允许您指定预期的 HTTP 状态代码(默认为 200)。可选参数as_list允许您指定对象是否作为列表返回。
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
@api.marshal_with(resource_fields, as_list=True)
def get(self):
return get_objects()
@api.marshal_with(resource_fields, code=201)
def post(self):
return create_object(), 201
Api.marshal_list_with()
装饰器严格等价于 Api.marshal_with(fields, as_list=True)()
resource_fields = api.model('Resource', {
'name': fields.String,
})
@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
@api.marshal_list_with(resource_fields)
def get(self):
return get_objects()
@api.marshal_with(resource_fields)
def post(self):
return create_object()
post 请求校验请求入参,get 请求查询数据序列化输出内容
from flask_restx import Resource, fields
user_input = api.model('UserModel', {
'username': fields.String(required=True),
'password': fields.String(required=True)
})
out_fields = api.model('UserInfo', {
'username': fields.String,
'email': fields.String,
'create_time': fields.DateTime(dt_format='rfc822')
})
@api.route('/api/user', endpoint='user')
class UserView(Resource):
@api.marshal_with(out_fields, envelope='users')
def get(self):
"""查询全部"""
users = models.Users.query.all()
return users
@api.expect(user_input, validate=True)
def post(self):
"""add user"""
print(f'请求参数: {api.payload}')
# 保存数据库
return {"msg": "create success"}
get请求查询结果
GET http://127.0.0.1:5000/api/user HTTP/1.1
{
"users": [
{
"username": "test",
"email": null,
"create_time": "Mon, 05 Sep 2022 11:13:16 -0000"
},
{
"username": "test1",
"email": null,
"create_time": "Mon, 05 Sep 2022 13:10:41 -0000"
},
{
"username": "test12",
"email": null,
"create_time": "Mon, 05 Sep 2022 13:10:55 -0000"
}
]
}
user_input 和 out_fields 模型可以合并为一个,有些不需要校验,但是可以输出的用readonly=True表示
from flask_restx import Resource, fields
user_model = api.model('UserModel', {
'id': fields.Integer(readonly=True),
'username': fields.String(required=True),
'password': fields.String(required=True),
'is_active': fields.Boolean(),
'email': fields.String(),
'create_time': fields.DateTime(dt_format='rfc822'),
'update_time': fields.DateTime(dt_format='rfc822')
})
@api.route('/api/user', endpoint='user')
class UserView(Resource):
@api.marshal_with(user_model, envelope='users')
def get(self):
"""查询全部"""
users = models.Users.query.all()
return users
@api.expect(user_model, validate=True)
def post(self):
"""add user"""
print(f'请求参数: {api.payload}')
# 保存数据库
return {"msg": "create success"}