如何使用FastApi在OpenAPI/Swagger中记录默认的无/null?

发布于 2025-01-28 16:15:31 字数 1176 浏览 1 评论 0 原文

使用ORM,我想执行一个发布请求,让一些具有 null 值的字段,该字段将在数据库中翻译成指定的默认值。

问题是OpenApi(Swagger) Docs ,忽略默认的 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)

docs 上的OpenAPI架构示例(请求正文)中,我们发现:

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

这不是可以的,因为我指定默认值是 none ,所以我期望这一点相反:

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

它将将 null 传递给 ID ,最后将在DB中解析为默认值(这是新生成的 uuid )。

Using a ORM, I want to do a POST request letting some fields with a null value, which will be translated in the database for the default value specified there.

The problem is that OpenAPI (Swagger) docs, ignores the default None and still prompts a UUID by default.

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)

In the OpenAPI schema example (request body) which is at the docs we find:

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

This is not ok, because I specified that the default value is None,so I expected this instead:

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

Which will pass a null to the ID and finally will be parsed in the db to the default value (that is a new generated UUID).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一袭水袖舞倾城 2025-02-04 16:15:31

当您声明可选参数时,用户不应在用 null 或 none 的请求中包含这些参数在python中),为了默认情况下,此类参数的值将为 none ,除非用户在发送请求时指定其他值。

因此,您所要做的就是使用 config schema_extra 来声明pydantic模型的自定义示例,如文档,如下所示。下面的示例将创建一个空的(IE, {} )在OpenAPI(Swagger UI)中的请求正文,可以成功提交(因为 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 属性,您可以使用以下内容删除 id 来自生成架构中模型的属性(灵感来自 schema> ):

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']

另外,如果您想将自定义示例添加到某些属性,则可以使用 field()(如所述 s e there );例如, some_attr:str = field(example =“ foo”)

另一个可能的解决方案是修改生成的OpenAPI模式,如

注意

ID:可选[UUID] =无 id:uuid = none 相同。如前所述,如Fastapi网站(请参阅此答案):

in 可选[str] 不使用Fastapi,但将允许
您的编辑器可以为您提供更好的支持和检测错误。


从那以后,Fastapi修改了他们的 documentation

联合的联盟[str,无] 将允许您的编辑给您
更好的支持和检测错误。

因此, id:union [uuid,none] = none same ID:可选[uuid] = none id :uuid =无。在 python 3.10+中,也可以使用 id:uuid | none = none (请参阅在这里) 。

按照(请参阅提供的链接中的 info 部分):

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

  =无
 

或:

  = query(default = none)
 

因为它将使用该作为默认值,然后将
不需要参数。

union [str,none] 部分允许您的编辑器提供更好
支持,,但不是告诉FastApi此参数不是的原因
必需

When you declare Optional parameters, users shouldn't include those parameters in the request specified with null or None (in Python), in order to be None. By default, the value of such parameters will be None, unless the user specifies some other value when sending the request.

Hence, all you have to do is to declare a custom example for the Pydantic model using Config and schema_extra, as described in the documentation and as shown below. The below example will create an empty (i.e., {}) request body in OpenAPI (Swagger UI), which can be successfully submitted (as ID is the only attribute of the model and is optional).

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

If the Table model included some other required attributes, you could add example values for those, as demonstrated below:

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

If you would like to keep the auto-generated examples for the rest of the attributes except the one for the ID attribute, you could use the below to remove ID from the model's properties in the generated schema (inspired by Schema customization):

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']

Also, if you would like to add custom example to some of the attributes, you could use Field() (as described here); for example, some_attr: str = Field(example="Foo").

Another possible solution would be to modify the generated OpenAPI schema, as described in Solution 3 of this answer. Though, the above solution is likely more suited to this case.

Note

ID: Optional[UUID] = None is the same as ID: UUID = None. As previously documented in FastAPI website (see this answer as well):

The Optional in Optional[str] is not used by FastAPI, but will allow
your editor to give you better support and detect errors.

Since then, FastAPI has revised their documentation with the following:

The Union in Union[str, None] will allow your editor to give you
better support and detect errors.

Hence, ID: Union[UUID, None] = None is the same as ID: Optional[UUID] = None and ID: UUID = None. In Python 3.10+, one could also use ID: UUID| None = None (see here).

As per FastAPI documentation (see Info section in the link provided):

Have in mind that the most important part to make a parameter optional
is the part:

= None

or the:

= Query(default=None)

as it will use that None as the default value, and that way make the
parameter not required.

The Union[str, None] part allows your editor to provide better
support, but it is not what tells FastAPI that this parameter is not
required
.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文