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 的最新版本。
我有一个简单的用户资源,它有一个 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 的最新版本。