FastAPIでORMを使って取得してきた結果をreturnしようと思ったときに
Traceback (most recent call last):
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/fastapi/applications.py", line 270, in __call__
await super().__call__(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/middleware/cors.py", line 84, in __call__
await self.app(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/routing.py", line 706, in __call__
await route.handle(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/fastapi/routing.py", line 255, in app
content = await serialize_response(
File "/home/raiu/work/project/porukatu/porukatu-back/porukatu-env/lib/python3.8/site-packages/fastapi/routing.py", line 141, in serialize_response
raise ValidationError(errors, field.type_)
pydantic.error_wrappers.ValidationError: 1 validation error for RepairShop
response -> 0
value is not a valid dict (type=type_error.dict)
というエラーが出てきて困った
pydantic.error_wrappers.ValidationError: 1 validation error for RepairShop
response -> 0
value is not a valid dict (type=type_error.dict)
とかって書いてるからreturnしているオブジェクトの辞書がおかしいよって怒られてるっぽい
気持ち悪いのが、似たようなコードで動くときと動かない場合があること。
解決策はFastAPIのドキュメントに書いてあった
https://fastapi.tiangolo.com/ja/tutorial/sql-databases/#use-pydantics-orm_mode
一応原因としてはレスポンスは辞書(dict)を期待しているが、実際にはSQLAlchemyのモデルが返ってきてしまっているので invalid となりエラーになってしまうということらしい
解決策
BaseModelを継承したクラスの定義に追記する
class RepairShop(BaseModel):
name: str
tel: str
link: str
description: str
lat: float
lon: float
star: int
outside_img: str
# ここを追加
class Config:
orm_mode = True
これで正しくシリアライズできるようになっていい感じに動くようになった