如何使用 Flask RestPlus 验证 POST 负载中的日期类型?

问题描述 投票:0回答:4

考虑以下因素:

from flask import Flask
from flask_restplus import Api, Resource, fields

app = Flask(__name__)
api = Api(app)
ns = api.namespace('ns')

payload = api.model('Payload', {
    'a_str': fields.String(required=True),
    'a_date': fields.Date(required=True)
})

@ns.route('/')
class AResource(Resource):

    @ns.expect(payload)
    def post(self):
        pass

如果我发布

{"a_str": 0, "a_date": "2000-01-01"}
,我会如预期得到 400, 因为
a_str
不是字符串。 然而,当我发布
{"a_str": "str", "a_date": "asd"}
时,我没有得到 400。 这里我也想得到 400,因为“asd”不是常见的日期格式。

我查看了

Date
doc 并 我看到有一个
format
parse
方法应该检查字符串是否采用通用日期格式。 不过这里好像不叫他们。

还有其他方法可以做到这一点吗? 目前我正在手动验证日期格式,但似乎 fask Restplus 应该能够为我做到这一点。

python post flask payload flask-restplus
4个回答
4
投票

正如 @andilabs 提到的,两次定义预期有效负载真的很奇怪。您可以仅使用

RequestParser
来定义预期负载,如下所示:

from flask import Flask, jsonify
from flask_restplus import Api, Resource, fields, reqparse, inputs

app = Flask(__name__)
api = Api(app)
ns = api.namespace('ns')

parser = reqparse.RequestParser()
parser.add_argument('a_str', type=str)
parser.add_argument('a_date', type=inputs.datetime_from_iso8601, required=True)


@ns.route('/')
class AResource(Resource):

    @ns.expect(parser)
    def get(self):

        try:  # Will raise an error if date can't be parsed.
            args = parser.parse_args()  # type `dict`
            return jsonify(args)
        except:  # `a_date` wasn't provided or it failed to parse arguments.
            return {}, 400


if __name__ == '__main__':
    app.run(debug=True)

使用

curl
进行测试:

$ curl -XGET -H "Content-type: application/json" -d '{"a_str": "Name", "a_date": "2012-01-01"}' 'http://127.0.0.1:5000/ns/'
{
  "a_date": "Sun, 01 Jan 2012 00:00:00 GMT", 
  "a_str": "Name"
}

4
投票

要验证,您可以添加参数 validate:

@ns.expect(payload, validate=True)

以下是文档链接: https://flask-restplus.readthedocs.io/en/stable/swagger.html#the-api-expect-decorator


4
投票

第 1 步:

pip install isodate

第二步:

pip install strict-rfc3339

步骤3:

from jsonschema import FormatChecker
api = Api(your_app,format_checker=FormatChecker(formats=("date-time",)))

第四步:

@api.expect(your_fields, validate=True)

参考: 开放问题:https://github.com/noirbizarre/flask-restplus/issues/204


0
投票

我在为 Flask-RESTX 创建自定义 UUID 字段时遇到了同样的问题。有很多关于如何创建自定义字段的示例,但是使用自定义字符串格式验证有效负载的记录有点少。

我的 UUID 字段解决方案:

  1. 创建 UUID 字段,并注意
    __schema_format__
    :
from flask_restx import fields

class UUIDField(fields.String):
    __schema_format__ = "uuid"

    def __init__(self, **kwargs):
        kwargs["example"] = "22a87929-ceb7-4825-a550-983eb45ebdbd"
        kwargs["description"] = "UUID"
        super().__init__(**kwargs)

    def format(self, value):
        try:
            return str(uuid.UUID(value))
        except ValueError:
            self.fail("Invalid UUID format")
  1. 向 Api 添加
    from jsonschema.FormatChecker
from jsonschema import FormatChecker
from flask_restx import Api

api = Api(
    version="some_version",
    title="some_api",
    description="Some API",
    doc="/api/v1",
    format_checker=FormatChecker(formats=("uuid",)),
)

  1. 创建命名空间、模型和端点
from flask_restx import Model, fields

ns = api.namespace("some_namespace", description="Some namespace")

my_model = Model(
    "My Model",
    {
        "some_uuid": UUIDField(
            required=True,
            description="Some UUID",
        ),
    },
)

ns.add_model(my_model.name, my_model)

@ns.route("/some_endpoint")
class SomeEndpointClass(Resource):
    @ns.expect(my_model, validate=True)
    def post(self):
        data = request.get_json() # Data format is checked
© www.soinside.com 2019 - 2024. All rights reserved.