Python pydantic model passing None as int value is not a valid integer (type=type_error.integer)

Viewed 182

I have a model which takes a few inputs including a sourceSiteId. This is an integer but also has many values as None. I have tried a few things with the model but still receive an error of value is not a valid integer (type=type_error.integer) when the value is None. Below is my model.

class LatLongModel(BaseModel):
    # id: str
    object_id: Optional[int] = None
    primo_id: Optional[int] = None
    name: Optional[str] = None
    entity_type: Optional[str] = None
    division_id: Optional[int] = None
    division: Optional[str] = None
    status: Optional[str] = None
    longitude: Optional[float] = None
    latitude: Optional[float] = None
    site_id: Optional[int] = None
    source_site_id: Optional[int] = None
    site_type: Optional[str] = None

I have also tried to do source_site_id: int = None and source_site_id: Optional[int] but no luck. What can I try to get this model to accept integers as well as None type for source_site_id?

2 Answers

You could try to find the issue by defining a __new__ method in your model. It might help you catch the problematic value(s) (empty string or something else) :

class LatLongModel(BaseModel):

    def __new__(cls, *args, **kwargs):
        for k,v in kwargs.items():
            print(f"'{k}' : {v.__repr__()} ({type(v)})")
        return super().__new__(cls)

    # [...]
    source_site_id: Optional[int] = None

l = LatLongModel(source_site_id="")

> 'source_site_id' : '' (<class 'str'>)
> Stacktrace [...] pydantic.error_wrappers.ValidationError: 1 validation error for LatLongModel
source_site_id
  value is not a valid integer (type=type_error.integer)

Some background, a field type int will try to coerce the value of None (or whatever you pass in) as an int. You can override this behavior by including a custom validator:

from typing import Optional
from pydantic import BaseModel, validator

class LatLongModel(BaseModel):
    # id: str
    object_id: Optional[int] = None
    primo_id: Optional[int] = None
    name: Optional[str] = None
    entity_type: Optional[str] = None
    division_id: Optional[int] = None
    division: Optional[str] = None
    status: Optional[str] = None
    longitude: Optional[float] = None
    latitude: Optional[float] = None
    site_id: Optional[int] = None
    source_site_id: Optional[int] = None
    site_type: Optional[str] = None


    # Custom validator here
    @validator('site_id', 'source_site_id', pre=True)
    def allow_none(cls, v):
        if v is None:
             return None
        else:
            return v
Related