python 自定义Pydantic类作为FastAPI主体参数

tvmytwxo  于 2023-02-15  发布在  Python
关注(0)|答案(1)|浏览(198)

Pydantic说你可以通过简单地定义__get_validators__方法来创建定制类,如果你想解析成一个有自己元类的类,或者出于其他原因不想继承BaseModel,这是很有用的。
但是,这在FastAPI中会在奇怪的地方失败,例如FastAPI不会将这样的类检测为主体参数,而总是认为它是查询参数。

from fastapi import FastAPI, Body
from fastapi.testclient import TestClient

app = FastAPI()

class NastyMetaClass(type):
    pass

class Foo(metaclass=NastyMetaClass):
    @classmethod
    def __get_validators__(cls):
        yield lambda value: True

@app.post("/implicit")
def foo(foo: Foo):  # This is supposed to work, but does not
    return "It worked"

@app.post("/explicit")
def foo_body(foo: Foo = Body(...)):  # The `= Body(...)` fixes it
    return "It worked"

client = TestClient(app)

response = client.post("/implicit", json={})
print(response.json())
# {'detail': [{'loc': ['query', 'foo'], 'msg': 'field required', 'type': 'value_error.missing'}]}

response = client.post("/explicit", json={})
print(response.json())
# It worked

如何让FastAPI识别自定义的Pydantic类?

vwkv1x7d

vwkv1x7d1#

根据FastAPI文档,当使用Body(...)时,您指示FastAPI将参数视为主体。因此,使用foo: Foo = Body(...)是告诉端点期望具有Foo属性的JSON主体的一种方式。
或者,您可以使用Dependencies来删除Foo参数,如下所示。您甚至可以简单地使用Depends()(即foo: Foo = Depends())作为避免代码重复的快捷方式。

from fastapi import Depends

@app.post("/implicit")
def foo(foo: Foo = Depends(Foo)):  # This should work
    return "It worked"

另外,/implicit路由需要foo作为查询参数的原因是,Foo继承自BaseModel,这将告诉FastAPI将其视为主体。因此,您应该有一个继承自BaseModel的类,在其中定义foo参数,并在端点中使用该模型。如Pydantic文档中所示。例如:

from pydantic import BaseModel
from typing import Optional

class Model(BaseModel):
    foo: Optional[Foo] = None
    
@app.post("/implicit")
def foo(m: Model):
    return "It worked"

相关问题