如何在 fastapi 响应中包含非 pydantic 类?
How to include non-pydantic classes in fastapi responses?
我想在路由的响应中包含自定义 class。我主要在我的应用程序中使用嵌套的 pydantic.BaseModel
s,所以最好 return 整个事情而不用编写从内部数据表示到路由 returns 的翻译。
只要 一切 继承自 pydantic.BaseModel
这是微不足道的,但我在后端使用 class 无法做到这一点.我能否以某种方式以 fastapi
接受的方式隐藏 class 的定义?我现在拥有的基本上是这样的:
main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Foo:
"""Foo holds data and can't inherit from `pydantic.BaseModel`."""
def __init__(self, x: int):
self.x = x
class Response(BaseModel):
foo: Foo
# plus some more stuff that doesn't matter right now because it works
@app.get("/", response_model=Response)
def root():
return Response(foo=Foo(1))
if __name__ == '__main__':
import uvicorn
uvicorn.run("main:app") # RuntimeError
它没有记录,但您可以使非 pydantic
class 与 fastapi
一起工作。您需要做的是:
告诉 pydantic
使用任意 classes 是可以的。它
将尝试使用 vars()
对它们进行 jsonify,所以只需要直接
数据容器可以工作——不要使用 property
、__slots__
或类似的东西 [1].
创建一个代理 BaseModel
,并告诉 Foo
如果有人提供它
询问它的模式——这就是 fastapi
s OpenAPI 页面所做的。
我只是假设你希望他们也工作,因为他们是
厉害了。
from fastapi import FastAPI
from pydantic import BaseModel, BaseConfig, create_model
app = FastAPI()
BaseConfig.arbitrary_types_allowed = True # change #1
class Foo:
"""Foo holds data and can't inherit from `pydantic.BaseModel`."""
def __init__(self, x: int):
self.x = x
__pydantic_model__ = create_model("Foo", x=(int, ...)) # change #2
class Response(BaseModel):
foo: Foo
@app.get("/", response_model=Response)
def root():
return Response(foo=Foo(1))
if __name__ == '__main__':
import uvicorn
uvicorn.run("main:app") # works
[1] 如果你想要更复杂的 jsonification,你需要通过 Config.json_encoders
显式地提供给 Response
class。
我想在路由的响应中包含自定义 class。我主要在我的应用程序中使用嵌套的 pydantic.BaseModel
s,所以最好 return 整个事情而不用编写从内部数据表示到路由 returns 的翻译。
只要 一切 继承自 pydantic.BaseModel
这是微不足道的,但我在后端使用 class 无法做到这一点.我能否以某种方式以 fastapi
接受的方式隐藏 class 的定义?我现在拥有的基本上是这样的:
main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Foo:
"""Foo holds data and can't inherit from `pydantic.BaseModel`."""
def __init__(self, x: int):
self.x = x
class Response(BaseModel):
foo: Foo
# plus some more stuff that doesn't matter right now because it works
@app.get("/", response_model=Response)
def root():
return Response(foo=Foo(1))
if __name__ == '__main__':
import uvicorn
uvicorn.run("main:app") # RuntimeError
它没有记录,但您可以使非 pydantic
class 与 fastapi
一起工作。您需要做的是:
告诉
pydantic
使用任意 classes 是可以的。它 将尝试使用vars()
对它们进行 jsonify,所以只需要直接 数据容器可以工作——不要使用property
、__slots__
或类似的东西 [1].创建一个代理
BaseModel
,并告诉Foo
如果有人提供它 询问它的模式——这就是fastapi
s OpenAPI 页面所做的。 我只是假设你希望他们也工作,因为他们是 厉害了。
from fastapi import FastAPI
from pydantic import BaseModel, BaseConfig, create_model
app = FastAPI()
BaseConfig.arbitrary_types_allowed = True # change #1
class Foo:
"""Foo holds data and can't inherit from `pydantic.BaseModel`."""
def __init__(self, x: int):
self.x = x
__pydantic_model__ = create_model("Foo", x=(int, ...)) # change #2
class Response(BaseModel):
foo: Foo
@app.get("/", response_model=Response)
def root():
return Response(foo=Foo(1))
if __name__ == '__main__':
import uvicorn
uvicorn.run("main:app") # works
[1] 如果你想要更复杂的 jsonification,你需要通过 Config.json_encoders
显式地提供给 Response
class。