Reputation: 2339
I have a fastapi implementation where the main.py
is:
@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()
And the following 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
The fisrt main.py
works, however if I want to use both EvergreenOutput
and MappingOutput
as the response models, it gives an error:
@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()
error is:
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)
The response without providing a type annotation, has the follwoing structure:
[
{
"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
}
},
Upvotes: 0
Views: 631
Reputation: 983
Response_model is static, it can not be switchable depends on data.
Your Error message
pydantic.error_wrappers.ValidationError: 200 validation errors for EvergreenOutput response -> 0 -> product_id
pointed out 'product_id' is not found on Mappings.
response_model
on path operation should be single model or list of one model.
If you want to return seperated 2 dictionary on single response
, then merge them on single pydantic Models like below.
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()
Upvotes: 1
Reputation: 983
It seems like your query is not mapped your pydantic model.
Try these,
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()
Upvotes: 0