Redis-OM模型无法被Pydantic识别为BaseModel的问题排查
在FastAPI缓存场景中使用redis-om时触发以下错误:
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'app.models.redis_models.Customer'> is a valid Pydantic field type. If you are using a return type annotation that is not a valid Pydantic field (e.g. Union[Response, dict, None]) you can disable generating the response model from the type annotation with the path operation decorator parameter response_model=None.
按继承链来看,Customer类继承自redis-om的HashModel,HashModel继承自RedisModel,而RedisModel应该继承自Pydantic的BaseModel,但通过issubclass检测时,Customer、HashModel、RedisModel均被判定不是BaseModel的子类。
测试代码
from pydantic import EmailStr import datetime from typing import Optional from pydantic import BaseModel from aredis_om import HashModel, get_redis_connection, Migrator from app.common.config import settings redis_conn = get_redis_connection(url=settings.REDIS_DATA_URL, decode_responses=True) class Customer(HashModel): first_name: str last_name: str email: EmailStr join_date: datetime.date age: int bio: Optional[str] class Meta: database = redis_conn Migrator().run() if __name__ == "__main__": if issubclass(Customer, BaseModel): print("Customer class is a subclass of BaseModel.") else: print("Customer class is NOT a subclass of BaseModel.")
运行结果
Customer class is NOT a subclass of BaseModel.
依赖版本
pydantic-settings = "^2.0.3" redis-om = "^0.2.1" fastapi-cache2 = {extras = ["redis"], version = "^0.2.1"} pydantic = "^2.0"
redis-om 0.2.1版本基于Pydantic V1开发,其RedisModel继承的是Pydantic V1的BaseModel;而当前使用的是Pydantic V2,Pydantic V2对底层架构做了完全重构,V1和V2的BaseModel属于不同版本的不兼容类。这就导致代码中导入的Pydantic V2的BaseModel,和redis-om继承的V1版本BaseModel不是同一个类,issubclass检测自然不通过,FastAPI也无法识别redis-om的模型为有效的Pydantic字段类型。
方法一:降级Pydantic到V1版本
将Pydantic及相关依赖降级到适配redis-om 0.2.1的V1版本,修改依赖配置如下:
pydantic-settings = "^1.0.3" redis-om = "^0.2.1" fastapi-cache2 = {extras = ["redis"], version = "^0.2.1"} pydantic = "~=1.10.12"
重新安装依赖后,redis-om的模型继承链会和Pydantic V1的BaseModel兼容,issubclass检测会通过,FastAPI也能正常识别模型。
方法二:转换为Pydantic V2模型返回
如果不想降级Pydantic,可以定义一个与Customer结构一致的Pydantic V2模型,在FastAPI接口中将redis-om的实例转换为该模型后返回:
# 定义Pydantic V2的响应模型 class CustomerResponse(BaseModel): first_name: str last_name: str email: EmailStr join_date: datetime.date age: int bio: Optional[str] # FastAPI接口示例 @app.get("/customer/{customer_id}", response_model=CustomerResponse) async def get_customer(customer_id: str): customer = await Customer.get(customer_id) # 将redis-om实例转换为Pydantic V2模型 return CustomerResponse(**customer.dict())
方法三:使用支持Pydantic V2的redis-om版本
redis-om的部分新版本已适配Pydantic V2,可以尝试升级到最新兼容版本,例如:
redis-om = "^0.4.0"
升级后验证模型是否能被FastAPI正常识别,若仍有问题需查看官方文档确认适配情况。
内容的提问来源于stack exchange,提问作者wonj

