Flask-Restx Api.model(strict=True) 允许未指定的参数

Flask-Restx Api.model(strict=True) allowing unspecified params

我有一个简单的用户资源,它有一个 put 方法来更新除用户密码之外的所有用户信息。根据 Flask-Restx 文档,当模型将 strict 和 validation 参数设置为 true 时,如果在请求中提供了未指定的参数,则会抛出验证错误。但是,这似乎对我不起作用。

模型定义:

from flask_restx import Namespace, Resource, fields, marshal

users_ns = Namespace("users")

user = users_ns.model(
    "user",
    {
        "user_name": fields.String(example="some_user", required=True),
        "email": fields.String(example="some.user@email", required=True),
        "is_admin": fields.Boolean(example="False"),
        "is_deactivated": fields.Boolean(example="False"),
        "created_date": fields.DateTime(example="2020-12-01T01:59:39.297904"),
        "last_modified_date": fields.DateTime(example="2020-12-01T01:59:39.297904"),
        "uri": fields.Url("api.user"),
    },
    strict=True,
)

user_post = users_ns.inherit(
    "user_post", user, {"password": fields.String(required=True)}
) # Used for when 

资源和方法定义:

from api.models import Users

class User(Resource):
    @users_ns.marshal_with(user)
    @users_ns.expect(user, validate=True)
    def put(self, id):
        """
        Update a specified user.
        """

        user = Users.query.get_or_404(id)
        body = request.get_json()

        user.update(body)

        return user

未通过测试:

def test_update_user_invalid_password_param(self, client, db):
        """ User endpoint should return 400 when user attempts to pass password param to update. """
        data = {
            "user_name": "some_user",
            "email": "some.user@email.com",
            "password": "newpassword",
        }

        response = client.put(url_for("api.user", id=1), json=data)

        assert response.status_code == 400

这里的response.status_code是200,因为在请求正文中传递的未指定参数不会抛出验证错误。

我是否使用不当的严格参数?我是不是误解了 strict 的行为?

更新:我已经从 Flask-RestX 存储库(可以找到 here)添加了对严格模型参数的测试,以获取有关预期行为的更多上下文:

def test_api_payload_strict_verification(self, app, client):
        api = restx.Api(app, validate=True)
        ns = restx.Namespace("apples")
        api.add_namespace(ns)

        fields = ns.model(
            "Person",
            {
                "name": restx.fields.String(required=True),
                "age": restx.fields.Integer,
                "birthdate": restx.fields.DateTime,
            },
            strict=True,
        )

        @ns.route("/validation/")
        class Payload(restx.Resource):
            payload = None

            @ns.expect(fields)
            def post(self):
                Payload.payload = ns.payload
                return {}

        data = {
            "name": "John Doe",
            "agge": 15,  # typo
        }

        resp = client.post_json("/apples/validation/", data, status=400)
        assert re.match("Additional properties are not allowed \(u*'agge' was unexpected\)", resp["errors"][""])

我已经有一段时间没有提到这个了,但据我所知,我认为你没有正确使用 strict 参数。从文档 here 中,:param bool strict 被定义为

:param bool strict: validation should raise an error when there is param not provided in schema

但是在你的最后一段代码中,你试图用字典 data 和请求的主体进行验证。

如果我还记得的话,对于这种任务你需要使用(正如你提到的)RequestParser. There's a good example of it here -

我通过从 Github 中提取最新版本的 Flask-RESTX 解决了我的问题。 2020 年 3 月在 Pypi 上发布 Flask-RESTX 版本 0.2.0 后,合并了模型的严格参数(有关更多上下文,请参阅 Flask-RESTX 存储库中已关闭的 issue)。我的困惑出现了,因为文档似乎代表了 master 的最新状态,而不是 Pypi 的最新版本。