0

我有一个简单的用户资源,它带有一个 put 方法来更新除用户密码之外的所有用户信息。根据 Flask-Restx 文档,当模型将严格和验证参数设置为 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,因为在请求正文中传递的未指定参数不会引发验证错误。

我是否不正确地使用了严格的参数?我是否误解了严格的行为?

更新:我已经添加了来自 Flask-RestX repo 的严格模型参数的测试(可以在这里找到)以获得更多关于预期行为的上下文:

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"][""])
4

2 回答 2

2

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

于 2021-01-04T15:17:12.493 回答
0

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

:param bool strict: 当模式中没有提供参数时,验证应该引发错误

但是在您的最后一段代码中,您正在尝试使用data带有请求正文的字典进行验证。

如果我再次记得,对于这类任务,您需要使用(并且正如您所提到的)RequestParser。这里有一个很好的例子——烧瓶——比@api.expect 更严格的输入数据?

于 2020-12-11T01:49:08.760 回答