How can I use pydantic to raise a ValueError if two specific bools are True?
I would need this to enforce mutually exclusivity.
AFAIK there is not anything in the current API allowing to pass a tuple of fields to a validator.
(See example below.). This leaves us with the only possibility to pass field and values to the validator, meaning the validation will be run twice.
1) either_i_am_true -> or_i_am
2) or_i_am ->either_i_am_true
from pydantic import BaseModel
class MyModel(BaseModel):
either_i_am_true: bool = False
or_i_am: bool = False
@validator(('either_i_am_true', 'or_i_am')) # note the tuple here
def mutually_exclusive(cls, v):
if v[0] and v[1]:
raise ValueError("either_i_am_true and' are 'or_i_am' mututally exclusive.")
return v
Try this:
@validator('or_i_am', always=True)
def mutually_exclusive(cls, v, values):
if values["either_i_am_true"] and v:
raise ValueError("either_i_am_true and' are 'or_i_am' mututally exclusive.")
return v
(The always=True means the validator should be called even if the field isn't specified. Since the default value is False, you actually don't even need to use always=True, since you'd have to have provided the value for validation to fail. But using always=True might be safer in case of future refactors; you can decide.)
@dmontagu Thanks.
Can we generalize this example for checking more than two values against each other?
Like 3, 4, ... n?
Yes, values will contain the values of all fields prior to the one being validated.
@dmontagu Thank you, this answers my question!
The missing piece was to know that values only contains those fields "prior to the one being validated". It neither contains all fields nor the field to validate itself.
Most helpful comment
@dmontagu Thank you, this answers my question!
The missing piece was to know that
valuesonly contains those fields "prior to the one being validated". It neither contains all fields nor the field to validate itself.