flask - 输入数据比@api.expect 更严格?

flask - something more strict than @api.expect for input data?

在我的 flask-restplus API 中,我不仅要检查输入数据,如下例所示

resource_fields = api.model('Resource', {
    'name': fields.String(default = 'string: name', required = True),
    'state': fields.String(default = 'string: state'),
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.expect(resource_fields, validate=True)
    def post(self):
        ...

必须有 'name' 字段并且可能有 'state' 字段,但还要检查是否没有其他字段(如果发生这种情况则引发错误)。 还有其他装饰器吗?我可以通过自定义函数检查输入数据的正确性吗?

请尝试使用 RequestParser (flask-restplus accepts both as documented here,而不是为您的字段使用字典。这样,您可以调用 parser.parse_args(strict=True),如果您的输入数据中存在任何未知字段,它将抛出 400 Bad Request 异常。

my_resource_parser = api.parser()
my_resource_parser.add_argument('name', type=str, default='string: name', required=True)
my_resource_parser.add_argument('state', type=str, default='string: state')

@api.route('/my-resource/<id>')
class MyResource(Resource):
    def post(self):
        args = my_resource_parser.parse_args(strict=True)
        ...

有关如何将 request_parser 与您的资源一起使用的更多指南,请查看 flask-restplus 存储库中的 ToDo example app

这是完成@shiv 的另一个答案。以下代码片段允许您在 Flask Restplus 生成的 Swagger 文档中记录您的有效负载。摘自关于 expect decorator:

的文档
my_resource_parser = api.parser()
my_resource_parser.add_argument('name', type=str, default='string: name', required=True)
my_resource_parser.add_argument('state', type=str, default='string: state')

@api.route('/my-resource/<id>', endpoint='with-parser')
class MyResource(Resource):
    @api.expect(my_resource_parser)
    def post(self):
        args = my_resource_parser.parse_args(strict=True)
        ...

对于那些想要继续使用 api.model 而不是请求解析器的人,可以迭代您的输入(假设列表)与模型。该模型的行为类似于字典。

from flask_restplus import abort

def check_exact(response_list, model):
    for response_dict in response_list:
        for key in response_dict:
            if key not in model:
                abort(400, "Non-specified fields added", field=key)

...

@ns.expect(my_model, validate=True)
def post(self, token):
    """Add new set of responses
    """
    check_exact(api.payload['responses'], my_model)
    ...