英文:
Greater than (gt) and less than (lt) parameters in FastAPI Path() do not work in Swagger UI
问题
以下是您要翻译的内容:
使用的版本
- python 3.9.9
- FastAPI 0.95.1
- uvicorn 0.22.0
- firefox 102.8.0
在这个示例中,路径参数 item_id
设置为有效范围大于 100 (gt=100
) 且小于 1000 (lt=1000
)。
然而,在 Swagger UI 中无法识别它。
ge
和 le
正常工作。
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", gt=100, lt=1000)]
):
return {"item_id": item_id}
使用 gt
和 lt
,约束既不显示在 UI 中,也不强制执行。
使用 ge
和 le
,约束都在 UI 中显示并强制执行。
英文:
Versions used
- python 3.9.9
- FastAPI 0.95.1
- uvicorn 0.22.0
- firefox 102.8.0
In this example, the path parameter item_id
is set up with a valid range > 100 (gt=100
) and < 1000 (lt=1000
).
However, it's not recognized in Swagger UI.
ge
and le
work fine.
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
item_id: Annotated[int, Path(title="The ID of the item to get", gt=100, lt=1000)]
):
return {"item_id": item_id}
with gt
and lt
, the constraints are neither shown in the UI nor enforced.
with ge
and le
, the constraints are both shown in the UI and enforced.
答案1
得分: 1
这似乎是与自动生成的 OpenAPI 架构有关的问题,该架构由 Swagger UI 用于提供交互式 API 文档。您可以直接查看架构:http://127.0.0.1:8000/openapi.json。根据您提供的示例,对于 item_id: int = Path(title="获取项目的ID", gt=100, lt=1000)
参数,您将看到:
{...,
"schema": {
"title": "获取项目的ID",
"exclusiveMaximum": 1000,
"exclusiveMinimum": 100,
"type": "integer"
},
"name": "item_id",
"in": "path"
}, ...
然而,根据Swagger 文档的描述,在使用 gt
和 lt
(意味着应该排除 maximum
和 minimum
值的情况下),OpenAPI 架构应该如下所示:
{...,
"schema": {
"title": "获取项目的ID",
"maximum": 1000,
"exclusiveMaximum": true,
"minimum": 100,
"exclusiveMinimum": true,
"type": "integer"
},
"name": "item_id",
"in": "path"
}...
因此,exclusiveMaximum
和 exclusiveMinimum
属性应该采用布尔值,而不是实际的数值。为了排除边界值,exclusiveMaximum
和 exclusiveMinimum
都应设置为 true
。这个问题之前已经在这里描述过,如果 FastAPI 迁移到 OpenAPI 3.1 时将得到解决(也请参阅Helen的回答)此主题)。在那之前,您可以查看以下解决方案。
可能的解决方案
解决方案 1
不要使用 gt
/lt
,您可以使用 ge
/le
。例如,如果 gt=100
和 lt=1000
,您可以改用 ge=101
和 le=999
。示例:
item_id: int = Path(title="获取项目的ID", ge=101, le=999)
解决方案 2
可以加载自己修改过的 OpenAPI 架构,如此处和此处所示,但即使 Swagger UI 显示了 minimum
和 maximum
值(如果使用了修改后的架构,类似于上面演示的架构),Swagger UI 仍然不会明确告诉用户应该排除 minimum
和 maximum
值(例如,使用大于/小于符号)。此外,如果用户向 item_id
参数传递了,例如,1000
值,前端不会进行验证,Swagger UI 不会显示验证错误消息(例如,值必须小于1000
),而如果使用 ge
和 le
参数,验证应该在后端进行,后端将以 422 Unprocessable Entity
错误回应,并在响应体中提供适当的验证错误消息。因此,生成的 OpenAPI 架构和 Swagger UI 都可能存在问题。
英文:
This seems to be an issue with the auto-generated OpenAPI schema, which is used by Swagger UI to provide the interactive API documentation. You could see the schema directly at: http://127.0.0.1:8000/openapi.json. Given the example you provided, for item_id: int = Path(title="The ID of the item to get", gt=100, lt=1000)
parameter, you would see:
{...,
"schema": {
"title": "The ID of the item to get",
"exclusiveMaximum": 1000,
"exclusiveMinimum": 100,
"type": "integer"
},
"name": "item_id",
"in": "path"
}, ...
However, as described in Swagger documentation, in the case of using gt
and lt
(meaning that the maximum
and minimum
values should be excluded from the range), the OpenAPI shcema should instead look like this:
{...,
"schema": {
"title": "The ID of the item to get",
"maximum": 1000,
"exclusiveMaximum": true,
"minimum": 100,
"exclusiveMinimum": true,
"type": "integer"
},
"name": "item_id",
"in": "path"
}...
Hence, exclusiveMaximum
and exclusiveMinimum
attributes should take a boolean value, not the actual number value itself. In order to exclude both the boundary values, both exclusiveMaximum
and exclusiveMinimum
should be set to true
. This issue has previously been described here and is meant to be resolved when/if FastAPI migrates to OpenAPI 3.1 (see Helen's answer around this topic as well). Until then, you may want to have a look at the following solutions.
Possible solutions
Solution 1
Instead of using gt
/lt
, you could use ge
/le
. If, for instance, gt=100
and lt=1000
, you could instead use ge=101
and le=999
. Example:
item_id: int = Path(title="The ID of the item to get", ge=101, le=999)
Solution 2
One could load their own modified OpenAPI shcema, as demonstrated here and here, but even though Swagger UI would display the minimum
and maximum
values (if a modified schema was used, similar to the one demonstrated above), Swagger UI would still not make it clear to the user that minimum
and maximum
values should be excluded (with greater/less than symbols, for instance). Also, if the user passed, for example, 1000
value to the item_id
parameter, the validation would not take place in the frontend and Swagger UI would not display a validation error message (e.g., Value must be less than 1000
)—which would happen if ge
and le
parameters wre used instead—but validation should rather take place in the backend, which would respond with a 422 Unprocessable Entity
error and an appropriate validation error message in the response body. Hence, there might be issues with both the generated OpenAPI shcema and Swagger UI as well.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论