如何使用 FastAPI 和 Swagger 允许任意查询参数?
- 2025-02-28 08:23:00
- admin 原创
- 51
问题描述:
注意:这个问题与这里的问题不同,因为我需要它与 Swagger 一起工作。
给定一个 FastAPIGET
端点,我想允许任意一组 URL 参数,同时保持 Swagger 支持。
我的用例是我想要支持一组类似 JSON API 的查询参数,例如:
/api/books/?include=author&sort=name,zip&sort[author]=-lname&fields=name,phone,street
使用方括号使我无法使用传统的类来建模查询参数,因此我直接使用Request
对象。但是,我想使用 Swagger 来测试端点。我找不到提供任意 URL 参数的方法。我很乐意将它们作为单个字符串输入。
人们可能会想到以下的事情:
def books(**params):
....
这给出了以下 curl 语句:
api/books?params=sort%5Bone%5D%3Dtwo'
我真正想要的是:
api/books?sort&one%5D%3Dtwo'
解决方案 1:
您可以使用Optional
字符串参数(如下例所示book_params
)通过 OpenAPI(Swagger UI)将查询参数作为单个字符串传递,例如。include=author&sort=name,zip&sort[author]=-lname&fields=name,phone,street
然后,您可以解析查询数据(使用urllib.parse.parse_qs
)以获取字典,如下所示。
以下示例还利用了此处描述的方法,以修复parse_qs
将单个值解析为列表的部分(例如,'foo=bar'
将被解析为foo = ['bar']
),同时还保留用户传递的列表的所有键值。例如,如果用户在 URL 中多次传递相同的键,即,例如,'foo=2&bar=7&foo=10'
使用dict(request.query_params)
检索查询参数将导致{"foo":"10","bar":"7"}
而不是{"foo":["2","10"],"bar":"7"}
。但是,以下示例中演示的方法(使用上述方法)也处理了这个问题,通过解析查询字符串(可以使用检索request.url.query
)并确保保留实际列表。
您可以检查此可选参数(即book_params
)是否为空,以决定是否使用book_params
(即通过 Swagger 发送请求)或Request
直接使用对象(即通过在浏览器的地址栏中输入 URL 发送请求,例如http://127.0.0.1:8000/api/books?include=author&sort=name,zip&sort[author]=-lname&fields=name,phone,street
,或使用其他客户端应用程序)读取查询参数。请确保将该可选参数(即book_params
)命名为唯一的名称,该名称不会成为实际参数的一部分。
from fastapi import FastAPI, Request
from typing import Optional
from urllib.parse import parse_qs
app = FastAPI()
@app.get("/api/books")
def books(request: Request, book_params: Optional[str] = None):
q_params = {}
if book_params is not None:
q_params = parse_qs(book_params, keep_blank_values=True)
else:
q_params = parse_qs(request.url.query, keep_blank_values=True)
d = dict((k, v if len(v)>1 else v[0])
for k, v in q_params.items())
return d
扫码咨询,免费领取项目管理大礼包!