在棉花糖中使用带有allow_blank的嵌套模式

问题描述 投票:0回答:2

我遇到了一个问题,我希望有人能指出我正确的方向。 我想使用棉花糖来验证具有嵌套模式的结构。 这是一个例子:

from marshmallow import Schema, fields
class userAddress(Schema):
    street = fields.Str(required=True)
    city = fields.Str(required=False)
    zipcode = fields.Int(required=True)
    

class user(Schema):
    name = fields.Str(required=True)
    address = fields.Nested(userAddress, required=False, allow_none=True, allow_blank=True)

user_instance = user()

user_data1 = {
    "name": "John Doe",
    "address": {
        "street": "Road to nowhere",
        "city": "St. Elsewhere",
        "zipcode": 666
    }
}

user_data2 = {
    "name": "John Doe, Jr.",
    "address": {}
}

我想要实现的是,两个 user_data 字典都经过验证,没有问题。如果键

address
存在,相应的字典应与模式
userAddress
中的定义匹配。但如果键
address
不存在或值为空字典,这是可以接受的。

但是这不起作用,结果如下:

>>> user_instance.validate(user_data1)
{}
>>> user_instance.validate(user_data2)
{'address': {'zipcode': ['Missing data for required field.'], 'street': ['Missing data for required field.']}}
>>>

不接受 user_data2 中

address
的空字典。

我尝试在

partial=True
中使用
validate
,但随后也接受了缺失的
name

python validation nested marshmallow
2个回答
0
投票

尝试使用 fields.Raw() 而不是 Nested()

from marshmallow import Schema, fields
class userAddress(Schema):
    street = fields.Str(required=True)
    city = fields.Str(required=False)
    zipcode = fields.Int(required=True)
    

class user(Schema):
    name = fields.Str(required=True)
    address = fields.Raw(userAddress)

user_instance = user()

user_data1 = {
    "name": "John Doe",
    "address": {
        "street": "Road to nowhere",
        "city": "St. Elsewhere",
        "zipcode": 666
    }
}

user_data2 = {
    "name": "John Doe, Jr.",
    "address": {}
}

0
投票

一种方法是在加载之前清理空字典:

class userAddress(Schema):
    street = fields.Str(required=True)
    city = fields.Str(required=False)
    zipcode = fields.Int(required=True)


class user(Schema):
    name = fields.Str(required=True)
    address = fields.Nested(userAddress, required=False, allow_none=True)

    @pre_load
    def clearemptydicts(self, data, **kwargs):
        for k, v in data.items():
            if isinstance(v, dict) and len(v) == 0:
                data[k] = None
        return data


user_instance = user()

user_data1 = {
    "name": "John Doe",
    "address": {
        "street": "Road to nowhere",
        "city": "St. Elsewhere",
        "zipcode": 666
    }
}

user_data2 = {
    "name": "John Doe, Jr.",
    "address": {}
}
print(user_instance.validate(user_data1))
print(user_instance.validate(user_data2))
© www.soinside.com 2019 - 2024. All rights reserved.