[Python] FastAPI基础:Query查询参数用法全面解析与实例
1. HTTP 请求格式
在开始写 Restful API 前,先简单的了解一下常规 HTTP 请求的格式,以便后续遇到问题知道从哪里排查,各部分的含义。下面是一个常规的 POST 请求的例子,各部分含义也都做了说明:
POST /api/data HTTP/1.1 # Request Line 请求行:包括请求方法 Method,请求 URI 和协议版本
Host: example.com # 请求头 - 请求的主机名
Content-Type: application/json # 请求头 - 请求体的数据类型
Authorization: Bearer abc123abc456 # 请求头 - 认证信息
Content-Length: 38 # 请求头 - 请求体的字节长度,帮助服务器正确解析主体内容
# 空行,分隔请求头和请求体
{"username": "John Doe", "gender": "male"} # 请求体
2. FastAPI 常见的路由函数请求参数类型
FastAPI 路由函数请求参数类型多种多样,常见的参数类型有:
- query 查询参数
- path 路径参数
- 请求头 header 参数
- 请求体 body 参数
对于这些不同的参数,FastAPI 框架整合了 pydantic 库进行统一的参数绑定和自动解析,下图是对应的源代码和类关系示意图。
FastAPI 在 fastapi/param_functions 中对 pydantic 库提供的 Path,Query,Body,Cookie 等类进行进一步的封装,可以很方便的使用它们完成请求参数的获取和解析,下面是 FastAPI 框架对 Query 类封装的源代码截图。
3. Query 查询参数
接下来开始本节的主体内容,介绍 Query 查询参数的使用。查询参数,直观的例子为:
http://127.0.0.1:8000/queryUserInfo?user_id=111&user_name=zhangsan&token=test_token
其中“?”后面跟着的这一串就是 HTTP 请求的 Query 参数。对应到 FastAPI,则是相应的路由函数的参数,并且这些查询参数无需其它修饰,直接在路由函数参数列表中添加即可,如下面的 user_id 就是一个查询参数。
async def query_user_info(user_id: int):
- 可选查询参数:查询参数可以是必填的或是可选的,可选通过 Optional 设置
- bool 查询参数:FastAPI 框架会对 bool 型参数自动转换
- list 查询参数:实现参数的多值查询
- 查询参数条件校验
3.1. 可选查询参数
查询参数可以是必填的或是可选的,可以通过 Optional 来设置参数是否可选,默认是必填的。举例如下:
from typing import Optional
from fastapi import FastAPI
# 实例化 FastAPI,代表当前服务进程
app = FastAPI()
# 通过 @app.get 装饰器创建一个 API 端点路由
# 查询参数:查询参数可以是必填的,也可以是可选的,可选通过 Optional 设置
# user_id 必填,如果没有,则会抛出请求参数校验异常错误
# user_name 可选,没有也不会抛参数校验异常,Optional[str] = None 表示参数要么是 str 类型的值,要么是 None
# token 带默认值,没有给值时,默认是 test_token
@app.get("/queryUserInfo", summary='获取用户信息')
async def query_user_info(user_id: int,
user_name: Optional[str] = None,
token: str = 'test_token'):
return {
"user_id": user_id,
"user_name": user_name,
"token": token
}
Swagger-UI 交互式接口文档效果如下:
接口调用效果如下:可以看到,没有提供 user_id 是会报错。
下面截图可以更加明显的看清这种错误:
3.2. bool 类型的查询参数
FastAPI 框架会对 bool 型的参数进行自动转换,把它们转化成 true/false。对于布尔类型的查询参数的值,可以是:true/false, 1/0, on/off,这些值都会被转换成 true/false,而其它值则会导致抛出参数校验异常。示例如下:
@app.get("/queryUser", summary='按性别查询用户')
async def query_user(is_man: bool):
return {
"is_man": is_man
}
运行效果如下:
3.3. list 查询参数
有时需要查询多个不同的值(多值查询,即对同一个变量同时传递多个不同的值),请求类似这样:
GET /queryGroup?group_name=group1&group_name=group6&group_name=group8
对于这样的查询请求,只需使用 list 类型的参数就可以实现。举例如下:
# List[str] = Query(["dev-team", "test-team"]) 指定参数为 list 类型,并设置了默认参数
@app.get("/queryGroup", summary='查询指定的组')
async def query_group(group_name: List[str] = Query(["dev-team", "test-team"])):
return {
"groups": group_name
}
运行效果如下:
3.4. 查询参数的条件校验
从源代码上可以看出 FastAPI 提供的 Query 封装,支持多种校验方式,如下图:
下面是一个简单的例子:
@app.get("/queryLimit", summary='参数条件限制')
async def query_limit(user_id: int = Query(..., gt=100, lt=200, title='用户ID', description='用户的唯一编码'),
user_name: str = Query(None, min_length=3, max_length=50, regex="^e"),
group_name: str = Query('dev-team', max_length=10)):
return {
'user_id': user_id,
'user_name': user_name,
'group_name': group_name
}
- gt, lt 和其它编程语言类似,都表示 大于、小于
- min_length, max_length 英文字面意思,校验文本长度
- regex="^e" 正则表达式,表示以 e 开头
Swagger-UI 交互式接口文档效果如下:
接口调用效果如下:
实际项目中一般很少使用 Query 查询参数,容易被枚举数据。