Pydantic模型datetime默认值配置错误导致FastAPI序列化失败求助
问题描述
我定义了一个带有datetime属性的简单Pydantic模型,代码如下:
from datetime import datetime from pydantic import BaseModel class Model(BaseModel): dt: datetime = datetime.now
当尝试将该模型序列化为JSON,或从FastAPI端点返回该模型时,出现了如下错误:
INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: 127.0.0.1:52831 - "POST /yard-manager/check_rule?id_request=1 HTTP/1.1" 500 Internal Server Error ERROR: Exception in ASGI application Traceback (most recent call last): File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\anyio\streams\memory.py", line 94, in receive return self.receive_nowait() File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\anyio\streams\memory.py", line 89, in receive_nowait raise WouldBlock anyio.WouldBlock During handling of the above exception, another exception occurred: Traceback (most recent call last): File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\base.py", line 43, in call_next message = await recv_stream.receive() File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\anyio\streams\memory.py", line 114, in receive raise EndOfStream anyio.EndOfStream During handling of the above exception, another exception occurred: Traceback (most recent call last): File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 404, in run_asgi result = await app( # type: ignore[func-returns-value] File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__ return await self.app(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\applications.py", line 269, in __call__ await super().__call__(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\applications.py", line 124, in __call__ await self.middleware_stack(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__ raise exc File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__ await self.app(scope, receive, _send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\cors.py", line 92, in __call__ await self.simple_response(scope, receive, send, request_headers=headers) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\cors.py", line 147, in simple_response await self.app(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\base.py", line 68, in __call__ response = await self.dispatch_func(request, call_next) File "c:\Users\ati_o\Projects\sms-digital\SSAB\ssab-ox-mes-pss-alg\rest_service\middleware.py", line 36, in check_header_token response = await call_next(request) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\base.py", line 46, in call_next raise app_exc File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\middleware\base.py", line 36, in coro await self.app(scope, request.receive, send_stream.send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\exceptions.py", line 93, in __call__ raise exc File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\exceptions.py", line 82, in __call__ await self.app(scope, receive, sender) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__ raise e File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__ await self.app(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\routing.py", line 670, in __call__ await route.handle(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\routing.py", line 266, in handle await self.app(scope, receive, send) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\starlette\routing.py", line 65, in app response = await func(request) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\routing.py", line 249, in app content = await serialize_response( File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\routing.py", line 149, in serialize_response return jsonable_encoder(response_content) File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\encoders.py", line 157, in jsonable_encoder return jsonable_encoder( File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\encoders.py", line 113, in jsonable_encoder encoded_value = jsonable_encoder( File "WINDOWS_USERNAME\scoop\apps\python310\current\lib\site-packages\fastapi\encoders.py", line 156, in jsonable_encoder raise ValueError(errors) ValueError: [TypeError("'builtin_function_or_method' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
解决方案
问题根源在于模型定义中的dt: datetime = datetime.now——你把datetime.now函数本身赋值给了dt的默认值,而非调用该函数生成的datetime对象。当Pydantic尝试序列化模型时,无法处理函数对象,因此抛出序列化错误。
有两种修复方式:
方式1:直接调用函数作为默认值
如果希望模型类定义时就确定默认时间,后续所有实例复用该时间,直接调用datetime.now():
from datetime import datetime from pydantic import BaseModel class Model(BaseModel): dt: datetime = datetime.now()
方式2:使用Pydantic的Field和默认工厂
如果希望每次创建模型实例时都生成最新的当前时间,推荐使用default_factory:
from datetime import datetime from pydantic import BaseModel, Field class Model(BaseModel): dt: datetime = Field(default_factory=datetime.now)
default_factory会在每次实例化模型时调用传入的函数,确保每个实例的dt都是最新时间;而直接调用datetime.now()的话,默认值会在类定义时就固定,所有实例共享同一个时间。
内容的提问来源于stack exchange,提问作者Atilla Ozgur
相关产品推荐
相关产品推荐

