FastAPI swagger 不喜欢通过查询参数传递的字符串列表,但端点在浏览器中工作
FastAPI swagger doesn't like list of strings passed via query parameter but endpoint works in browser
我在 FastAPI 中的 REST API 端点有问题,它通过单个查询参数接受字符串列表。此端点的用法示例是:
http://127.0.0.1:8000/items/2?short=false&response=this&response=that
此处,名为 'response' 的参数接受 FastAPI 教程中 Query Parameters and String Validation 部分中记录的字符串列表。端点在浏览器中按预期工作。
但是,它在 Swagger 文档中不起作用。单击 'Execute' 以测试端点时,标记为 'Add string item' 的按钮会晃动。 Swagger UI 似乎无法使用嵌入式查询参数创建预期的 URL(如图 1 所示)。
端点的代码如下。我试过验证和不验证。
@app.get("/items/{item_ID}")
async def getQuestion_byID(item_ID: int = Path(
...,
title = "Numeric ID of the question",
description = "Specify a number between 1 and 999",
ge = 1,
le = 999
), response: Optional[List[str]] = Query(
[],
title="Furnish an answer",
description="Answer can only have letters of the alphabet and is case-insensitive",
min_length=3,
max_length=99,
regex="^[a-zA-Z]+$"
), short: bool = Query(
False,
title="Set flag for short result",
description="Acceptable values are 1, True, true, on, yes"
)):
"""
Returns the quiz question or the result.
Accepts item ID as path parameter and
optionally response as query parameter.
Returns result when the response is passed with the item ID.
Otherwise, returns the quiz question.
"""
item = question_bank.get(item_ID, None)
if not item:
return {"question": None}
if response:
return evaluate_response(item_ID, response, short)
else:
return {"question": item["question"]}
感谢任何帮助。
如 here, this happens due to that OpenAPI applies the pattern
(as well as minimum
and maximum
constraints) to the schema of the array
itself, not just the individual items
in the array. If you checked the OpenAPI schema at http://127.0.0.1:8000/openapi.json 所述,您会看到 response
参数的架构如下所示(即验证也应用于 array
本身):
{
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"required": false,
"schema": {
"title": "Furnish an answer",
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "array",
"items": {
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "string"
},
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"default": []
},
"name": "response",
"in": "query"
}
解决方案 1
如前所述 here, you could use a Pydantic constr
而不是使用该约束指定 items
:
my_constr = constr(regex="^[a-zA-Z]+$", min_length=3, max_length=99)
response: Optional[List[my_constr]] = Query([], title="Furnish an...", description="Answer can...")
解决方案 2
保持 response
参数不变。从 http://127.0.0.1:8000/openapi.json 复制 OpenAPI 架构,从 response
(array
) 中删除 pattern
(以及 minimum
和 maximum
属性)模式并将 OpenAPI 模式保存到新文件(例如,my_openapi.json
)。它应该是这样的:
...
{
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"required": false,
"schema": {
"title": "Furnish an answer",
"type": "array",
"items": {
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "string"
},
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"default": []
},
"name": "response",
"in": "query"
},
...
然后,在您的应用中,指示 FastAPI 使用该架构:
import json
app.openapi_schema = json.load(open("my_openapi.json"))
解决方案 3
由于上述解决方案要求您在每次进行更改或添加新内容时都复制和编辑架构 endpoints/parameters,因此您宁愿按照 here 所述修改 OpenAPI 架构。这将使您免于 copying/editing 模式文件。确保在代码末尾添加以下内容(在定义所有路由之后)。
from fastapi.openapi.utils import get_openapi
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="FastAPI",
version="0.1.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["maxLength"]
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["minLength"]
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["pattern"]
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
在上述所有解决方案中,通常在 OpenAPI 中 response
(即 (query) maxLength: 99 minLength: 3 pattern: ^[a-zA-Z]+$
)下显示的约束注释不会出现(因为 Swagger 会从约束应用于 array
,而不是 items
),但 doesn't seem to be a way to preserve that。但是,在解决方案 2 和 3 中,您可以修改上面 JSON
代码片段中显示的 "in"
属性,以手动添加注释。但是,由于 HTML
元素等由 Swagger 控制,因此整个注释将出现在括号内并且约束之间没有换行符。尽管如此,您仍然可以通过在 Query
参数的 description
中指定它们来告知用户有关 items
的约束。
我在 FastAPI 中的 REST API 端点有问题,它通过单个查询参数接受字符串列表。此端点的用法示例是:
http://127.0.0.1:8000/items/2?short=false&response=this&response=that
此处,名为 'response' 的参数接受 FastAPI 教程中 Query Parameters and String Validation 部分中记录的字符串列表。端点在浏览器中按预期工作。
但是,它在 Swagger 文档中不起作用。单击 'Execute' 以测试端点时,标记为 'Add string item' 的按钮会晃动。 Swagger UI 似乎无法使用嵌入式查询参数创建预期的 URL(如图 1 所示)。
端点的代码如下。我试过验证和不验证。
@app.get("/items/{item_ID}")
async def getQuestion_byID(item_ID: int = Path(
...,
title = "Numeric ID of the question",
description = "Specify a number between 1 and 999",
ge = 1,
le = 999
), response: Optional[List[str]] = Query(
[],
title="Furnish an answer",
description="Answer can only have letters of the alphabet and is case-insensitive",
min_length=3,
max_length=99,
regex="^[a-zA-Z]+$"
), short: bool = Query(
False,
title="Set flag for short result",
description="Acceptable values are 1, True, true, on, yes"
)):
"""
Returns the quiz question or the result.
Accepts item ID as path parameter and
optionally response as query parameter.
Returns result when the response is passed with the item ID.
Otherwise, returns the quiz question.
"""
item = question_bank.get(item_ID, None)
if not item:
return {"question": None}
if response:
return evaluate_response(item_ID, response, short)
else:
return {"question": item["question"]}
感谢任何帮助。
如 here, this happens due to that OpenAPI applies the pattern
(as well as minimum
and maximum
constraints) to the schema of the array
itself, not just the individual items
in the array. If you checked the OpenAPI schema at http://127.0.0.1:8000/openapi.json 所述,您会看到 response
参数的架构如下所示(即验证也应用于 array
本身):
{
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"required": false,
"schema": {
"title": "Furnish an answer",
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "array",
"items": {
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "string"
},
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"default": []
},
"name": "response",
"in": "query"
}
解决方案 1
如前所述 here, you could use a Pydantic constr
而不是使用该约束指定 items
:
my_constr = constr(regex="^[a-zA-Z]+$", min_length=3, max_length=99)
response: Optional[List[my_constr]] = Query([], title="Furnish an...", description="Answer can...")
解决方案 2
保持 response
参数不变。从 http://127.0.0.1:8000/openapi.json 复制 OpenAPI 架构,从 response
(array
) 中删除 pattern
(以及 minimum
和 maximum
属性)模式并将 OpenAPI 模式保存到新文件(例如,my_openapi.json
)。它应该是这样的:
...
{
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"required": false,
"schema": {
"title": "Furnish an answer",
"type": "array",
"items": {
"maxLength": 99,
"minLength": 3,
"pattern": "^[a-zA-Z]+$",
"type": "string"
},
"description": "Answer can only have letters of the alphabet and is case-insensitive",
"default": []
},
"name": "response",
"in": "query"
},
...
然后,在您的应用中,指示 FastAPI 使用该架构:
import json
app.openapi_schema = json.load(open("my_openapi.json"))
解决方案 3
由于上述解决方案要求您在每次进行更改或添加新内容时都复制和编辑架构 endpoints/parameters,因此您宁愿按照 here 所述修改 OpenAPI 架构。这将使您免于 copying/editing 模式文件。确保在代码末尾添加以下内容(在定义所有路由之后)。
from fastapi.openapi.utils import get_openapi
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="FastAPI",
version="0.1.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["maxLength"]
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["minLength"]
del openapi_schema["paths"]["/items/{item_ID}"]["get"]["parameters"][1]["schema"]["pattern"]
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
在上述所有解决方案中,通常在 OpenAPI 中 response
(即 (query) maxLength: 99 minLength: 3 pattern: ^[a-zA-Z]+$
)下显示的约束注释不会出现(因为 Swagger 会从约束应用于 array
,而不是 items
),但 doesn't seem to be a way to preserve that。但是,在解决方案 2 和 3 中,您可以修改上面 JSON
代码片段中显示的 "in"
属性,以手动添加注释。但是,由于 HTML
元素等由 Swagger 控制,因此整个注释将出现在括号内并且约束之间没有换行符。尽管如此,您仍然可以通过在 Query
参数的 description
中指定它们来告知用户有关 items
的约束。