Introduction
This article will introduce how to use Pydantic to validate that either one of two optional fields is not None
.
Validating That Either Field1 or Field2 is Not None
Before we can start validating that either one of two optional fields is not None
, we need to set up a Pydantic model with these fields. In this example, we'll create a Example
model with two optional string fields: field1
and field2
.
from typing import Optional
from pydantic import BaseModel
class Example(BaseModel):
field1: Optional[str] = None
field2: Optional[str] = None
Here, we import the Optional
type from the typing module, which allows us to define optional fields. We also import the BaseModel
class from the pydantic
module, which we'll use to create our model.
In the Example
class, we define two optional string fields: field1
and field2
. We set their default values to None
, which means they are optional and can be None
if no value is provided.
To validate that either field1
or field2
is not None, we'll use the validator
decorator in Pydantic. This decorator allows us to define custom validation logic for a field or set of fields.
In our Example
class, we'll define a validator
method called check_either_not_none
that takes in two arguments: v
and values
. The v
argument represents the value of the field being validated (field1
or field2
), while the values
argument represents a dictionary of all the values being validated.
from typing import Optional, Any
from pydantic import BaseModel, validator
class Example(BaseModel):
field1: Optional[str] = None
field2: Optional[str] = None
@validator('field1', 'field2', pre=True)
def check_either_not_none(cls, v: Optional[str], values: dict, **kwargs: Any) -> Optional[str]:
if not kwargs.get("validate_assignment"):
return v
if v is None and values.get('field2') is None:
raise ValueError('either field1 or field2 must not be None')
return v
Here, we decorate the check_either_not_none
method with the validator decorator and pass in the names of the fields we want to validate (field1
and field2
) as strings.
In the method, we first check if the value of the field being validated (v
) is None. If it is, we then check if the value of the other field (field2
) is also None using values.get('field2')
. If both fields are None
, we raise a ValueError
with a message indicating that at least one of the fields must not be None
.
If either field is not None
, we simply return the value of the field being validated (v
).
With this validation logic in place, we can now create an instance of the Example
model and test our validation:
example = Example(field1='hello', field2=None)
In this example, field1
is set to 'hello'
and field2
is set to None
. Because field1
is not None
, our validation passes and we can create an instance of the Example
model without any errors.
If we were to try creating an instance with both fields set to None
, we would get a ValueError
:
example = Example(field1=None, field2=None)
This will raise a ValueError
with the message either field1
or field2
must not be None
.