棉花糖不从嵌套列表返回验证错误

时间:2021-02-20 11:25:13

标签: python marshmallow

我从 Marshmallow 开始,我想用它来验证我的数据(来自 api 请求)。 我创建了以下架构:

from marshmallow import fields, Schema
from marshmallow.validate import Range

class RequestTopSchema(Schema):
    upperTarget = fields.Float(required=True, validate = validate.Range(min = 0.0, max = 80.0))
    lowerTarget = fields.Float(required=True)
    data = fields.Nested("Values", many = True, required = False)
 
class Values(Schema):
    timestamp = fields.String(required=True)
    value = fields.Float(required =True, validate = Range(min = 0.0, max = 100.0))

request_top_schema = RequestTopSchema()

然后我传入以下数据:

request_data = {
  "lowerTarget": 10,
  "upperTarget": 20,
  "data": [
        {
        "timestamp": "2020-01-01 11:20:00+02:00",
        "value": 156.7
        },
        {
        "timestamp": "2020-01-01 11:25:00+02:00",
        "value": "46.7"
        }
   ]
}

request_top_schema.validate(request_data)

并接收:

{}

但是,由于我的第一个值大于 100,而我的第二个值是字符串格式 - 我希望这会返回两个错误。

在顶层,至少有些事情是有效的 - 如果我传入:

request_data = {
  "lowerTarget": "20",
  "upperTarget": 180,
  "data": [
        {
        "timestamp": "2020-01-01 11:20:00+02:00",
        "value": 156.7
        },
        {
        "timestamp": "2020-01-01 11:25:00+02:00",
        "value": "46.7"
        }
   ]
}

request_top_schema.validate(request_data)

我收到:{'upperTarget': ['Must be greater than or equal to 0.0 and less than or equal to 100.0.']} 所以我确实收到了超出范围的验证错误,但是,我的 lowerTarget 是一个字符串并没有失败。

1 个答案:

答案 0 :(得分:0)

更新 - 我已经设法解决了这个问题。问题是将嵌套模式作为字符串传递。如果我将它们更改为对象,它会按预期工作。

然而,仍然存在一个问题:fields.Float() 接受浮点数作为字符串——比如“100.0”。 这似乎是一个已知问题:https://github.com/marshmallow-code/marshmallow/pull/755 当前的解决方案是使用自定义浮动字段。


class Float(fields.Float):
    def _deserialize(self, value, attr, data, **kwargs):
        if isinstance(value, float) or isinstance(value, int):
            return value
        else:
            raise ValidationError('Field should be int or float')

class RequestTopSchema(Schema):
    upperTarget = Float(required=True, validate = validate.Range(min = 0.0, max = 80.0))
    lowerTarget = Float(required=True)
    data = fields.Nested(Values, many = True, required = False)
 
class Values(Schema):
    timestamp = fields.String(required=True)
    value = fields.Float(required =True, validate = Range(min = 0.0, max = 100.0))