2023-03-11

How to Validate That Either One of Two Optional Fields Is Not None in Pydantic

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.

python
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.

python
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:

python
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:

python
example = Example(field1=None, field2=None)

This will raise a ValueError with the message either field1 or field2 must not be None.

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!