Pydantic可选参数尚未准备好,因此类型仍然是ForwardRef



我有以下代码:

端点.py

from __future__ import annotations # this is important to have at the top
from fastapi import FastAPI
from pydantic import BaseModel
class MyOpt(BaseModel):
fieldfirst: str = "S"
fieldsecond: int = 1
fieldthird: str = None
fieldforth: list = []
fieldfifth: int
fieldsixth: list = [None, None]
fieldseventh: str = None 
fieldeighth: Optional[int] = None
fieldnineth: Optional[str] = None
fieldtenth: Optional[list] = [None, None] 
from typing import List, Optional
# Create object for fastAPI
app = FastAPI()
# START API ENDPOINTS
@app.get("/", tags=["root"])
def root():
return {"message": "REST API."}
# -- TESTING ENDPOINTS --
@app.get(
"/health", 
name="health", 
tags=["root"],
summary="Test connection to API",
status_code=200
)
def health():
return {"type": "complete"}
@app.post(
"/send_instruction", 
name="send_instruction", 
tags=["web"],
)
def send_instruction(myopts: MyOpt = None):    
return {"result": "ok"}

run_api.py:

import uvicorn
if __name__ == "__main__":
uvicorn.run("endpoints:app", host="0.0.0.0", port=8822, reload=True, access_log=False)

当我调用api(python3run_api.py(时,只有当我发送MyOpt:的任何可选值时,我才会得到以下错误

File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/applications.py", line 269, in __call__
await super().__call__(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/exceptions.py", line 93, in __call__
raise exc
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/exceptions.py", line 82, in __call__
await self.app(scope, receive, sender)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 670, in __call__
await route.handle(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 266, in handle
await self.app(scope, receive, send)
File "/home/ubuntu/.local/lib/python3.10/site-packages/starlette/routing.py", line 65, in app
response = await func(request)
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/routing.py", line 217, in app
solved_result = await solve_dependencies(
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 557, in solve_dependencies
) = await request_body_to_args(  # body_params checked above
File "/home/ubuntu/.local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 692, in request_body_to_args
v_, errors_ = field.validate(value, values, loc=loc)
File "pydantic/fields.py", line 857, in pydantic.fields.ModelField.validate
File "pydantic/fields.py", line 1074, in pydantic.fields.ModelField._validate_singleton
File "pydantic/fields.py", line 1121, in pydantic.fields.ModelField._apply_validators
File "pydantic/class_validators.py", line 313, in pydantic.class_validators._generic_validator_basic.lambda12
File "pydantic/main.py", line 686, in pydantic.main.BaseModel.validate
File "pydantic/main.py", line 339, in pydantic.main.BaseModel.__init__
File "pydantic/main.py", line 1038, in pydantic.main.validate_model
File "pydantic/fields.py", line 833, in pydantic.fields.ModelField.validate
pydantic.errors.ConfigError: field "fieldnineth" not yet prepared so type is still a ForwardRef, you might need to call SatOpt.update_forward_refs().

为了发送请求,我使用Postman,并在Body中使用JSON格式的原始格式:

{"fieldfirst": "S", "fieldsecond": 1, "fieldthird": "a test", "fieldforth": [1,2], "fieldfifth": 42, "fieldsixth": [[1, 8, 3], [1, 9, 2]], "fieldseventh": "yey", "fieldnineth": "VV"}

我的代码出了什么问题?

from typing import List, Optional

应在类定义之前

我看不出接受的答案是如何解决问题的。如果问题是键入时缺少导入,那么在收到任何传入请求之前,代码一执行,我就会看到ListOptionalNameError异常。我想问题中的例子被简化和调整了,可能还有其他的变化解决了问题。

我遇到了一个类似的问题,我只是添加了错误消息所暗示的内容。具体而言:

from typing import Literal
from pydantic import BaseModel
class BaseEntity(BaseModel):
type: str
id: str
name: str
class EntityA(BaseEntity):
type: Literal["a"] = "a"
children: list['EntityB']   # This is a forward-ref, this is what causes the Pydantic error.
class EntityB(BaseEntity):
type: Literal["b"] = "b"
data: str | None
Entity = EntityA | EntityB
# This is where the Pydantic exception gets raised.
# Saying: 'pydantic.errors.ConfigError: field "children" not yet prepared so type is still a ForwardRef, you might need to call `EntityA.update_forward_refs()`.
a = EntityA(
id="foo",
name="Foo",
children=[EntityB(id="foo.bar", name="Bar", data="This is my data")]
) 

解决方案是添加以下行:

EntityA.update_forward_refs()

在定义了所有前向refs之后,在这种情况下是在定义了EntityB之后。

相关内容

最新更新