当我使用 Union 参数时,为什么我的 FastAPI Router 无法解析 Pydantic 的 Enum 类型?

问题描述 投票:0回答:1

我的问题

这是我的三个 Pydantic 模型的定义:

class SplitType(str, enum.Enum):
    AUTO = "auto"
    CUSTOM = "custom"


class DocumentConfigBase(BaseModel):
    '''
    document config detail
    '''
    model_config = ConfigDict(use_enum_values=True)
    mode: Optional[SplitType] = Field(
        default=SplitType.AUTO, validate_default=True)
    chunk_size: Optional[str] = "800"
    identifier: Optional[str]
    text_preprocessing_rules: Dict[str, Any]


class DocumentConfigCreate(BaseModel):
    '''
    document config create
    '''
    knowledge_id: int
    config: DocumentConfigBase


class SheetConfigCreate(BaseModel):
    '''
    need to update
    '''
    knowledge_id: int
    pass


class ImageConfigCreate(BaseModel):
    '''
    need to update
    '''
    knowledge_id: int
    pass

在第一个模型中,我将

mode
字段定义为枚举类型。然后我写了 Router 代码。

@router.post("/config", response_model=KnowledgeConfigModel)
def create_knowledge_config(user_id: Annotated[int, Body()], config_type: Annotated[KnowledgeType, Body()], knowledge_config: Union[DocumentConfigCreate, SheetConfigCreate, ImageConfigCreate], session: Session = Depends(get_db)):

    print('knowledge_config', knowledge_config)

    try:
        knowledge_model = KnowledgeConfigService.create(
            operator=user_id, config_type=config_type,
            knowledge_config=knowledge_config, session=session)
        print('knowledge_model', knowledge_model)
        if knowledge_model is None:
            raise HTTPException(
                status_code=404, detail="Config create failed")
        return knowledge_model
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e)) from e

我在knowledge_config字段中使用了Union类型,但是当我使用以下参数请求此API时,出现错误:“detail”:“'config'”。

{
  "user_id": 0,
  "config_type": "document",
  "knowledge_config": {
    "knowledge_id": 1,
    "config": {
      "mode": "auto",
      "chunk_size": "1000",
      "identifier": "string",
      "text_preprocessing_rules": {}
    }
  }
}

并且代码中的打印语句(

print('knowledge_config', knowledge_config)
)输出
knowledge_config knowledge_id=1
。剩下的参数好像都丢了。

我的尝试:

  1. 当我不传递mode参数时,没有错误。我获取了我传递的所有参数,并且
    mode
    字段自动设置为“auto”。
  2. 当我停止使用 Union 类型并仅使用
    knowledge_config: DocumentConfigCreate
    时,没有错误。我获取了传递的所有参数,并且
    mode
    字段也自动设置为“auto”。

因此,我相信我的参数没有错误;问题可能在于我使用了 Union 类型,导致 FastAPI 解析失败。

我是Python新手,请帮我解决这个问题,非常感谢!

python-3.x fastapi pydantic-v2
1个回答
0
投票

当您使用 Union 定义输入参数时,FastAPI 应在验证阶段选择正确的类型。 我不知道确切的算法,但您可以将其视为 FastAPI 将尝试以未知顺序使用这些模型,并且 FastAPI 将选择第一个通过验证的模型作为此参数的类型。

要解决这个问题,您可以使用受歧视的工会。这样您就可以向 FastAPI 提供选择正确模型的标准。

在某些情况下,您可以通过向所有模型添加

model_config = ConfigDict(extra="forbid")
来解决此问题。如果存在未知字段,这将迫使模型验证失败。因此,当输入 JSON 中有字段
SheetConfigCreate
时,
config
将不会通过验证。

以下方法也有帮助。 定义新类型:

KnowledgeConfig: TypeAlias = Annotated[Union[DocumentConfigCreate, SheetConfigCreate, ImageConfigCreate], Field(union_mode='left_to_right')]
并使用它代替
Union[DocumentConfigCreate, ...]

© www.soinside.com 2019 - 2024. All rights reserved.