SQLModel继承Pydantic BaseModel为何datetime字段未自动转类型?
问题:SQLModel实例化时未自动将ISO字符串转换为datetime类型
用户确认SQLModel继承自Pydantic的BaseModel(通过__mro__查看),但以下测试代码执行时类型对比失败:
from datetime import datetime from uuid import uuid4, UUID from sqlmodel import SQLModel, Field class SomeModel(SQLModel, table=True): timestamp: datetime id: UUID = Field(default_factory=lambda: str(uuid4()), primary_key=True) def test_some_model(): m = SomeModel(**{'timestamp': datetime.utcnow().isoformat()}) assert type(m.timestamp) == datetime
报错信息:
E AssertionError: assert <class 'str'> == datetime
用户尝试过使用Field的default_factory等方法仍未解决,寻求FastAPI/SQLModel相关解答。
原因分析
当SQLModel设置table=True时,它会同时兼容SQLAlchemy ORM和Pydantic的特性,但默认情况下直接通过类实例化传入原始数据时,不会触发Pydantic的字段验证与类型转换——这是SQLModel为适配数据库操作性能,在ORM模型实例化流程中跳过了Pydantic的完整校验逻辑导致的。
解决方案
有两种可行的解决方式:
方式1:使用model_validate触发Pydantic校验
调用Pydantic的model_validate方法可以强制执行字段类型转换和校验,替换直接实例化的方式:
def test_some_model(): m = SomeModel.model_validate({'timestamp': datetime.utcnow().isoformat()}) assert type(m.timestamp) == datetime
方式2:拆分输入模型与ORM模型
如果需要明确区分数据输入校验和数据库操作模型,可以单独定义一个不设置table=True的SQLModel子类用于接收并转换数据,再映射到ORM模型:
class SomeModelCreate(SQLModel): timestamp: datetime class SomeModel(SQLModel, table=True): timestamp: datetime id: UUID = Field(default_factory=uuid4, primary_key=True) def test_some_model(): create_data = SomeModelCreate(**{'timestamp': datetime.utcnow().isoformat()}) m = SomeModel.model_validate(create_data) assert type(m.timestamp) == datetime
额外修正点
你的id字段定义存在类型不匹配问题:声明为UUID类型,但default_factory返回的是字符串(str(uuid4())),应直接返回UUID对象:
id: UUID = Field(default_factory=uuid4, primary_key=True)
内容的提问来源于stack exchange,提问作者Octavio del Ser
相关产品推荐
相关产品推荐

