Marshmallow: required=True depending on the presence of other fields

Created on 18 Feb 2019  路  3Comments  路  Source: marshmallow-code/marshmallow

Hello,

I was wondering whether there is a way in marshmallow to have a field to be required depending on the value of another field.

e.g.:

{ 'name':'John', 'status':'unoccupied' }
{ 'name':'Martha', 'status':'occupied', 'job':'waitress' }

I'd like to know if there is a way to make the field job required if status == 'occupied'

Thanks

question

Most helpful comment

I don't think there is a way to compute the value of required based on the data, but this behavior can be achieved with schema-level validation.

https://marshmallow.readthedocs.io/en/3.0/extending.html#schema-level-validation

from marshmallow import Schema, fields, validates_schema, ValidationError

class TestSchema(Schema):
    field_a = fields.Integer(required=False)
    field_b = fields.Integer(required=False)

    @validates_schema
    def validate_b_requires_a(self, data):
        if 'field_b' in data and 'field_a' not in data:
            raise ValidationError('field_a is required when field_b is set')

TestSchema().load({'field_b': 2})
# marshmallow.exceptions.ValidationError: {'_schema': ['field_a is required when field_b is set']}

All 3 comments

I don't think there is a way to compute the value of required based on the data, but this behavior can be achieved with schema-level validation.

https://marshmallow.readthedocs.io/en/3.0/extending.html#schema-level-validation

from marshmallow import Schema, fields, validates_schema, ValidationError

class TestSchema(Schema):
    field_a = fields.Integer(required=False)
    field_b = fields.Integer(required=False)

    @validates_schema
    def validate_b_requires_a(self, data):
        if 'field_b' in data and 'field_a' not in data:
            raise ValidationError('field_a is required when field_b is set')

TestSchema().load({'field_b': 2})
# marshmallow.exceptions.ValidationError: {'_schema': ['field_a is required when field_b is set']}

Side note: vuelidate has a dedicated requiredIf validator (which I use), so it seems to be a common use case.

https://monterail.github.io/vuelidate/#sub-builtin-validators

Thank you very much, it worked like a charm, I made something more in the line of:

@validate_schema
def validate_requires(self, data):
    if data['field_b'] == 'foo' and 'field_a' not in data :
        raise ValidationError('field_a is required when field_b is of type foo')
Was this page helpful?
0 / 5 - 0 ratings