[英]Using both pydantic models as response throws error
我有一个 fastapi 实现,其中main.py
是:
@app.get(
"/licence_ol/",
summary="Query Licence info by product id",
response_description="Successful Query",
response_model=list[EvergreenOutput],
tags=[Tags.items]
)
def get_product_id(session: Session = Depends(get_session))-> list[EvergreenOutput]:
query = select(Evergreen).where(Evergreen.product_id == Mapping.eim_product_id).limit(200)
return session.exec(query).fetchall()
以及以下schemas.py
:
class Mapping(SQLModel,table=True):
id_seq: Optional[int] = Field(default=None,primary_key=True)
eim_product_id: Optional[int] = None
mem_product_id: Optional[int] = None
vendor: Optional[str] = None
name: Optional[str] = None
eim_name: Optional[str] = None
product_alias: Optional[str] = None
lev: Optional[int] = None
manufacturer: Optional[str] = None
class MappingOutput(SQLModel):
eim_product_id: Optional[int] = None
mem_product_id: Optional[int] = None
vendor: Optional[str] = None
name: Optional[str] = None
eim_name: Optional[str] = None
product_alias: Optional[str] = None
lev: Optional[int] = None
manufacturer: Optional[str] = None
class Evergreen(SQLModel,table=True):
id_seq: Optional[int] = Field(default=None,primary_key=True)
product_id: int
phase_type: Optional[str] = None
phase_start: Optional[date] = None
phase_end: Optional[date] = None
product_name: Optional[str] = None
software_product_version_name: Optional[str] = None
software_product_version_id: Optional[int] = None
class EvergreenOutput(SQLModel):
product_id: int
phase_type: Optional[str] = None
phase_start: Optional[date] = None
phase_end: Optional[date] = None
product_name: Optional[str] = None
software_product_version_name: Optional[str] = None
software_product_version_id: Optional[int] = None
main.py
有效,但是如果我想同时使用EvergreenOutput
和MappingOutput
作为响应模型,它会报错:
@app.get(
"/licence_ol/",
summary="Query Licence info by product id",
response_description="Successful Query",
response_model=list[EvergreenOutput,MappingOutput],
tags=[Tags.items]
)
def get_product_id(session: Session = Depends(get_session))-> list[EvergreenOutput,MappingOutput]:
query = select(Evergreen,Mapping).where(Evergreen.product_id == Mapping.eim_product_id).limit(200)
return session.exec(query).fetchall()
错误是:
INFO: 127.0.0.1:53172 - "GET /licence_ol/ HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 404, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\fastapi\applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
raise exc
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\middleware\exceptions.py", line 75, in __call__
raise exc
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\middleware\exceptions.py", line 64, in __call__
await self.app(scope, receive, sender)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\routing.py", line 680, in __call__
await route.handle(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\routing.py", line 275, in handle
await self.app(scope, receive, send)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\starlette\routing.py", line 65, in app
response = await func(request)
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\fastapi\routing.py", line 253, in app
content = await serialize_response(
File "C:\Users\45291029\Documents\venv\ml\lib\site-packages\fastapi\routing.py", line 139, in serialize_response
raise ValidationError(errors, field.type_)
pydantic.error_wrappers.ValidationError: 200 validation errors for EvergreenOutput
response -> 0 -> product_id
field required (type=value_error.missing)
不提供类型注释的响应具有以下结构:
[
{
"Evergreen": {
"id_seq": 344,
"phase_start": "2011-07-22",
"product_name": "HTTP Server (IHS)",
"software_product_version_id": 359483,
"phase_end": "2018-04-30",
"product_id": 359496,
"phase_type": "Generally Available",
"software_product_version_name": "IBM HTTP Server v8.0"
},
"Mapping": {
"eim_product_id": 359496,
"mem_product_id": 19,
"name": "HTTP Server (IHS)",
"product_alias": "IHS",
"manufacturer": "IBM",
"id_seq": 0,
"vendor": "IBM",
"eim_name": "HTTP Server (IHS)",
"lev": 100
}
},
Response_model 为static,不能根据数据切换。
您的错误信息
pydantic.error_wrappers.ValidationError:EvergreenOutput 响应的 200 个验证错误 -> 0 -> product_id
指出在映射中找不到“product_id”。
路径操作上的response_model
应该是单个 model 或一个 model 的列表。
如果你想在单个response
上返回分离的 2 字典,然后将它们合并到单个 pydantic 模型上,如下所示。
class FuncResult(BaseModel):
Evergreen: EvergreenOutput
Mapping: MappingOutput
@app.get(
"/licence_ol/",
summary="Query Licence info by product id",
response_description="Successful Query",
response_model=list[FuncResult],
tags=[Tags.items]
)
def get_product_id(session: Session = Depends(get_session)) -> list[EvergreenOutput, MappingOutput]:
query = select(Evergreen, Mapping).where(Evergreen.product_id == Mapping.eim_product_id).limit(200)
return session.exec(query).fetchall()
看起来你的查询没有映射你的 pydantic model。
试试这些,
class EvergreenOutput(SQLModel):
product_id: int
phase_type: Optional[str] = None
phase_start: Optional[date] = None
phase_end: Optional[date] = None
product_name: Optional[str] = None
software_product_version_name: Optional[str] = None
software_product_version_id: Optional[int] = None
# below line is added
mapping: list[MappingOutput]
...
@app.get(
"/licence_ol/",
summary="Query Licence info by product id",
response_description="Successful Query",
response_model=list[EvergreenOutput],
tags=[Tags.items]
)
def get_product_id(session: Session = Depends(get_session)) -> list[EvergreenOutput, MappingOutput]:
query = select(Evergreen, Mapping).where(Evergreen.product_id == Mapping.eim_product_id).limit(200)
return session.exec(query).fetchall()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.