![](/img/trans.png)
[英]How to return Pydantic model using Field aliases instead of names in FastAPI?
[英]How to return a response with a list of different Pydantic models using FastAPI?
我正在使用 FastAPI 創建一個 API 來計算圖形上的最短路徑。 我的回應由節點和關系組成。
這些節點可以是不同的類型,這意味着它們可以具有不同的屬性:
class SchoolNode(BaseModel):
uid: int
code: Optional[str]
label: str = 'school'
class PersonNode(BaseModel):
uid: int
name: Optional[str]
surname: Optional[str]
label: str = 'person'
class PetNode(BaseModel):
uid: int
name: Optional[str]
surname: Optional[str]
label: str = 'pet'
我的回復遵循以下格式:
class Response(BaseModel):
links: List[Link]
nodes: List[Union[SchoolNode, PersonNode, PetNode]]
start: int
end: int
請注意,我無法更改響應格式,因為我的 output 將由基於 d3js 的自定義庫使用,該庫需要以這種特定格式輸入數據。
您可以在此處查看包含完整代碼示例的要點。
API 成功運行,但“節點”屬性內的響應無法理解必須選擇哪個 model。 預期的 output 是:
{
'links': [
{'source': 1, 'target': 123, 'type': 'GO_TO_SCHOOL'},
{'source': 100, 'target': 123, 'type': 'GO_TO_SCHOOL'},
],
'nodes': [
{'uid': 1, 'label': 'person', 'name': 'Bob', 'surname': 'Foo'},
{'uid': 123, 'label': 'school', 'code': 'ABCD'},
{'uid': 100, 'label': 'person', 'name': 'Alice', 'surname': 'Bar'}
],
'start': 1,
'end': 100
}
而得到的output是:
{
"links": [
{"source": 1, "target": 123, "type": "GO_TO_SCHOOL"},
{"source": 123, "target": 100, "type": "GO_TO_SCHOOL"}
],
"nodes": [
{"uid": 1, "code": null, "label": "person"},
{"uid": 123, "code": "ABCD", "label": "school"},
{"uid": 100, "code": null, "label": "person"}
],
"start": 1,
"end": 100
}
在這里您可以看到第一個和第三個節點如何顯示第一個節點 (SchoolNode) 的屬性而不是正確的屬性 (PersonNode)
我應該如何更改我的響應以返回正確的 output? 我嘗試使用類似 if-then-else 的邏輯
nodes = []
for node in graph['nodes']:
if node['label'] == 'person':
node.append(PersonNode(**node)
elif:
...
但沒有任何改變。
我也嘗試使用Field(..., discriminator='label')
我想這是解決這個問題的正確方法,但目前沒有成功。
感謝您的幫助,在此先感謝!
感謝@Chris並點擊他發給我的鏈接,我可以解決這個問題。
解決方案是創建一個獨特的 model UnionNode
,其__root__
屬性帶有Field(..., discriminator='label')
。 此外,節點中的 label 屬性必須具有Literal
類型。
class SchoolNode(BaseModel):
id: int
label: Literal['school']
code: Optional[str]
class PersonNode(BaseModel):
id: int
label: Literal['person']
name: Optional[str]
surname: Optional[str]
class PetNode(BaseModel):
id: int
label: Literal['pet']
name: Optional[str]
surname: Optional[str]
class UnionNode(BaseModel):
__root__: Union[SchoolNode, PersonNode, PetNode] = Field(..., discriminator='label')
class Response(BaseModel):
links: List[Link]
nodes: List[UnionNode]
start: int
end: int
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.