当前位置: 首页 > 知识库问答 >
问题:

如何使用FastAPI在OpenAPI/Swagger中记录缺省None/null?

靳祺然
2023-03-14

使用 ORM,我想做一个 POST 请求,让一些具有值的字段,这些字段将在数据库中转换为那里指定的默认值。

问题是OpenAPI(Swagger)文档忽略默认的None,并且默认情况下仍然提示UUID

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
from uuid import UUID
import uvicorn


class Table(BaseModel):
    # ID: Optional[UUID]      # the docs show a example UUID, ok
    ID: Optional[UUID] = None # the docs still shows a uuid, when it should show a null or valid None value.

app = FastAPI()  
    
@app.post("/table/", response_model=Table)
def create_table(table: Table):
    # here we call to sqlalchey orm etc.
    return 'nothing important, the important thing is in the docs'
    
if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

在我们找到的文档中的OpenAPI模式示例(请求正文)中:

{
 "ID": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}

这是不行的,因为我指定默认值为 None,所以我期望这样做:

{
 "ID": null, # null is the equivalent of None here
}

这会将一个 null 传递给 ID,最后将在数据库中解析为默认值(即新生成的 UUID)。

共有1个答案

韦衡
2023-03-14

当您声明可选参数时,用户不必在其请求中包含这些参数(用null值指定)才能成为null。参数的默认值将是null,除非用户在发送请求时指定其他值。

因此,您所要做的就是使用< code>Config和< code>schema_extra为Pydantic模型声明一个自定义的< code >示例,如文档中所述,如下所示。下面的示例将在OpenAPI (Swagger UI)中创建一个空的(即< code>{})请求体,该请求体可以成功提交(因为< code>ID是模型的唯一属性,并且是可选的)。

class Table(BaseModel):
    ID: Optional[UUID] = None
    
    class Config:
        schema_extra = {
            "example": {
            }
        }

@app.post("/table/", response_model=Table)
def create_table(table: Table):
    return table

如果模型包含一些其他必需属性,则可以为这些属性添加示例值,如下所示:

class Table(BaseModel):
    ID: Optional[UUID] = None
    some_attr: str
    
    class Config:
        schema_extra = {
            "example": {
                "some_attr": "Foo"
            }
        }

如果要保留除 ID 属性之外的其余属性的自动生成示例,则可以使用以下方法从生成的架构中的模型属性中删除 ID(受架构自定义的启发):

class Table(BaseModel):
    ID: Optional[UUID] = None
    some_attr: str
    some_attr2: float
    some_attr3: bool
    
    class Config:
        @staticmethod
        def schema_extra(schema: Dict[str, Any], model: Type['Table']) -> None:
            del schema.get('properties')['ID']

此外,如果您想将自定义示例添加到某些属性中,您可以使用字段()(如下所述);例如,some_attr: str=字段(示例="Foo")

另一种可能的解决方案是修改生成的 OpenAPI 架构,如本答案的解决方案 3 中所述。不过,上述解决方案可能更适合这种情况。

< code>ID:可选[UUID] =无与< code>ID: UUID =无相同。如之前在FastAPI网站中记录的那样(参见此答案):

Optional[str] 中的 Optional 不被 FastAPI 使用,但可以让您的编辑器为您提供更好的支持并检测错误。

从那时起,FastAPI 修改了他们的文档,内容如下:

< code>Union[str,None]中的联合将允许您的编辑器为您提供更好的支持并检测错误。

因此,ID:Union[UUID,无]=无ID:可选[UUID]=无ID:UUID=无相同。在Python 3.10中,也可以使用ID:UUID|无=无

根据 FastAPI 文档(请参阅提供的链接中的信息部分):

请记住,使参数可选的最重要部分是以下部分:

= None

或:

= Query(default=None)

因为它将使用<code>None</code>作为默认值,这样就不需要参数。

Union[str, None] 部分允许编辑器提供更好的支持,但它并不能告诉 FastAPI 此参数不是必需的。

 类似资料:
  • 有什么方法可以记录下面的查询吗? 其中查询参数名称是动态的,将从客户端接收。 我正在使用最新的Swagger API。

  • OpenAPI3.0规范规定,没有任何类型的模式将匹配任何数据类型。 没有类型的模式匹配任何数据类型--数字、字符串、对象等等。 因此,对此进行建模的正确方法是下面的Swagger定义,其中没有属性: 但是,每个开放问题Swagger-core#3834,Java值都映射到OpenAPI类型,而不是任意类型。如上所述,这意味着这样的API返回或接受不是OpenAPI的类型是不正确的,例如、、等。

  • 我正在生成Restendpoint,包括向生成的代码添加Openapi/Swagger注释。 虽然它可以很好地处理基本类型,但我在自定义类方面有一些问题。 现在我有很多自定义类的重复模式条目(使用@Schema(实现=MyClass.class)),但至少需要的信息在那里。然而,我想找到一种方法来删除重复的模式条目,同时保留附加信息。 在一个讨论$ref和缺乏兄弟属性的github问题上,我发现了

  • 我正在使用从以下依赖项导入的Swagger/OpenAPIV3注释创建应用程序的API描述: 其中一个批注是批注,它接受名为的属性,该属性允许字符串数组: 现在,我想使用在枚举类上构造的自定义方法,该方法返回允许的字符串数组,因此不需要在每次向枚举添加类型时添加该方法。以便我们可以这样使用它: 现在这是无法编译的,因为在执行注释时不知道该方法。是否有这样的解决方案允许在SwaggerV3注释属性值

  • 我想为我的Swagger API创建一个递归规范。这个概念似乎没有出现在Swagger文档中,所以我怀疑这是不可能的。因此,我也愿意接受任何由Swagger支持的替代解决方案。 例如,我试图创建一个类似文档的结构。每个文档都有部分,每个部分都有文本和自己的部分。我计划使用这样的APIendpoint: http://a.b.com/docs/{文档ID} http://a.b.com/docs/{

  • 这个问题显然可以通过将整个webapp移动到非根上下文路径来解决。但是,我不能走这条路由,因为客户端已经知道并使用它的某些endpoint。 如何让springfox和swagger在这种情况下工作呢?