什么是查询参数
简单来说,就是你访问的浏览器的输入的地址的?
后面的 键值对。
在FastAPI中,叫做Query Parameters ,指的就是是在HTTP请求中,URL的查询字符串部分传递的参数。这些参数是键值对的形式,通常用于过滤、排序或限制从服务器返回的数据量。
例如,在一个RESTful API中,你可能有一个用于获取用户列表的端点,可以使用查询参数来指定要返回的用户数量:
GET /users?limit=10
在这个例子中,limit
就是一个查询参数,它的值为 10
,表示我们希望服务器只返回前10个用户。
在 FastAPI 中,你可以很容易地定义和使用查询参数。FastAPI 使用类型提示(Type hints)来自动处理这些参数。关于Optional和Query,这个在后面会讲到。
代码示例
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Optional[str] = Query(None, max_length=50)):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return results
在这个例子中,我们定义了一个名为 read_items
的路径操作,它接受一个可选的 q
参数。这个参数默认为 None
,并且最大长度被限制为50个字符。如果客户端提供了 q
参数,那么其值将被添加到响应结果中。
当客户端发送如下请求时:
GET /items?q=Hello
注意点
当我们使用查询参数时,不同于路径参数的是,参数是不需要和我们定义的函数的中的参数的顺序一致的。
服务器会返回类似这样的JSON响应:
{
"items": [
{
"name": "Foo"
},
{
"name": "Bar"
}
],
"q": "Hello"
}
通过这种方式,你可以轻松地在FastAPI应用中使用查询参数,并且FastAPI的类型检查系统会确保传入的参数符合预期的类型和约束。
路径参数和查询参数的组合
在FastAPI中,路径参数和查询参数可以很容易地一起使用。以下是一个结合了路径参数和查询参数的例子:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/users/{user_id}/items/")
async def read_items(user_id: int, q: Optional[str] = Query(None, max_length=50)):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return {f"User {user_id} items": results}
在这个例子中,我们定义了一个名为 read_items
的路径操作,它接受一个名为 user_id
的路径参数和一个名为 q
的查询参数。
user_id
: 这是一个整数类型的路径参数,用于指定要获取哪个用户的所有项目。q
: 这是一个可选的字符串类型查询参数,默认值为None
,最大长度被限制为50个字符。
当客户端发送如下请求时:
GET /users/42/items?q=Hello
服务器会返回类似这样的JSON响应:
{
"User 42 items": {
"items": [
{
"name": "Foo"
},
{
"name": "Bar"
}
],
"q": "Hello"
}
}
这个例子展示了如何同时使用路径参数(user_id
)和查询参数(q
),以便根据用户ID过滤项目并添加额外的搜索条件。
注意点
路径参数必须按照顺序传参,它实际上是一个占位符,已经挖好的坑,对应的 参数就去占坑,站错位置了,就会发生意外。
- 实际上,这种组合用法,在我的实际开发项目中,用的并不多,甚至是从来没有使用过!是否选择,看你个人喜好了。
必须参数
当我们在函数中定义了一个参数之后,只写了其类型,或者没有写其类型的时候,都表示这是一个必须填写的值,如果加了默认值,则不是必须的。
代码示例
from fastapi import FastAPI, Query
from typing import Optional
app = FastAPI()
@app.get("/a/")
async def a(q: str):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return results
@app.get("/b/")
async def b(q: str = Query(...)):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return results
@app.get("/c/")
async def c(q: Optional[str] = None):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return results
@app.get("/d/")
async def d(q: Optional[str]):
results = {"items": [{"name": "Foo"}, {"name": "Bar"}]}
if q:
results["q"] = q
return results
我们分别来解释一下这四个路由函数
您的代码中包含了四个不同的查询参数处理方式。下面是每个方法的解释:
/a/
:
@app.get("/a/")
async def a(q: str):
这个路径操作使用了默认的查询参数定义方式,即通过类型提示来指定查询参数 q
的类型为字符串。这意味着客户端在发送请求时必须提供 q
参数,否则会引发一个错误。
/b/
:
@app.get("/b/")
async def b(q: str = Query(...)):
这个路径操作使用了FastAPI中的特殊标记 ...
来表示必需的查询参数。这与第一个例子相同,意味着客户端在发送请求时必须提供 q
参数。
/c/
:
@app.get("/c/")
async def c(q: Optional[str] = None):
这个路径操作使用了可选的查询参数,其默认值为 None
。这意味着客户端可以选择是否提供 q
参数。如果提供了,其值将被添加到响应结果中;如果没有提供,则默认值为 None
。
/d/
:
@app.get("/d/")
async def d(q: Optional[str]):
这个路径操作也使用了可选的查询参数,但没有提供默认值。虽然这与第三个例子类似,但FastAPI的行为会有所不同:在这个例子中,如果客户端没有提供 q
参数,FastAPI将返回一个400错误(Bad Request),而不是使用默认值 None
。
访问http://localhost:8000/docs来分别看看效果
综上所述,您应该根据需求选择合适的查询参数定义方式。如果您希望客户端必须提供某个查询参数,请使用第一种或第二种方法。如果您希望客户端可以自由选择是否提供查询参数,请使用第三种方法,并提供适当的默认值。