首页 > 解决方案 > 如何在 FastAPI 正文验证中使用可区分的联合类型?(模型上的联合)

问题描述

我从 Typescript 中知道一个名为Discriminate unions的概念。这是您放置 2 个结构(类等)的地方,类型取决于结构的值。我试图通过Pydantic验证在FastAPI中实现类似的事情。我可以收到两种不同的请求有效负载。是一个还是另一个取决于变量。如果是,则应由 验证,如果是,则应由 验证。我如何实现这一目标?找不到任何其他解决方案。accountTypecreativeRegistrationPayloadCreativebrandRegistrationPayloadBrand

问题是它要么返回

unexpected value; permitted: 'creative' (type=value_error.const; given=brand; permitted=('creative',))

或者它根本不起作用。

class RegistrationPayloadBase(BaseModel):
    first_name: str
    last_name: str
    email: str
    password: str


class RegistrationPayloadCreative(RegistrationPayloadBase):
    accountType: Literal['creative']


class RegistrationPayloadBrand(RegistrationPayloadBase):
    company: str
    phone: str
    vat: str
    accountType: Literal['brand']

class A(BaseModel):
    b: Union[RegistrationPayloadBrand, RegistrationPayloadCreative]

def main():
    A(b={'first_name': 'sdf', 'last_name': 'sdf', 'email': 'sdf', 'password': 'sdfds', 'accountType': 'brand'})

if __name__ == '__main__':
    main()

标签: pythonvalidationfastapipython-typingpydantic

解决方案


您应该使用__root__andparse_obj来代替。

from typing import Union

from pydantic import BaseModel


class PlanetItem(BaseModel):
    id: str
    planet_name: str 
    # ...

class CarItem(BaseModel):
    id: str
    name: str
    # ...

class EitherItem(BaseModel):
    __root__: Union[PlanetItem, CarItem]



@app.get("/items/{item_id}", response_model=EitherItem)
def get_items(item_id):
    return EitherItem.parse_obj(response) # Now you get either PlanetItem or CarItem

信用:https ://github.com/tiangolo/fastapi/issues/2279#issuecomment-787517707


推荐阅读