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

Marshmallow not returning validation errors from a nested List

我从棉花糖开始,我想用它来验证我的数据(来自 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,而我的第二个值是字符串格式 - 我预计这会 return 两个错误。

在顶层,至少有一些东西是有效的——如果我通过:

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 是一个字符串并没有失败。

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

但是仍然存在一个问题: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))