Use nested Schema with allow_blank in marshmallow

Viewed 1082

I'm stuck with a problem and I hope somebody can point me in the right direction. I'd like to use marshmallow to validate a structure with a nested schema. Here is an example:

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": {}
}

What I would like to achieve, is that both user_data dicts are validated without a problem. If the key address is present the corresponding dictionary should match the definitions in schema userAddress. But it is acceptable if the key address is not present or the value is an empty dictionary.

However this is not working, here is the result:

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

The empty dictionary for address in user_data2 is not accepted.

I tried to use partial=True in validate but then a missing name is accepted, too.

1 Answers

Try fields.Raw() instead of 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": {}
}
Related