FastAPI 中解析逗号分隔的多个 Query 参数
在 FastAPI 开发中,我们经常需要处理前端传递的多个值作为查询参数。一种常见的场景是客户端希望通过单个查询参数传递多个值,通常使用逗号分隔的形式,例如:?ids=1,2,3,4。本文将详细介绍如何在 FastAPI 中优雅地解析这类参数。
方法一:使用自定义依赖项
这种方法通过创建一个依赖项函数来解析逗号分隔的字符串,并将其转换为列表。
from typing import List
from fastapi import Depends, FastAPI, HTTPException, Query
app = FastAPI()
def parse_comma_separated_ids(ids: str = Query(None)) -> List[int]:
"""
将逗号分隔的字符串转换为整数列表
"""
if ids is None:
return []
try:
# 分割字符串并转换为整数
return [int(id.strip()) for id in ids.split(",")]
except ValueError:
raise HTTPException(
status_code=400,
detail="IDs must be integers separated by commas"
)
@app.get("/items/")
async def read_items(ids: List[int] = Depends(parse_comma_separated_ids)):
return {"ids": ids}在这个示例中,我们定义了一个名为 parse_comma_separated_ids 的依赖项函数。它接收一个可选的字符串参数 ids,该参数通过 Query(None) 从查询参数中获取。函数内部将逗号分隔的字符串分割成列表,并尝试将每个元素转换为整数。如果转换失败,则抛出 HTTP 异常。然后在路由函数中,我们通过 Depends 注入这个依赖项来获取解析后的 ID 列表。
方法二:使用 Pydantic 模型与自定义验证器
利用 Pydantic 的强大功能,我们可以创建一个模型来处理和验证逗号分隔的参数。
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel, validator
app = FastAPI()
class ItemQueryParams(BaseModel):
ids: Optional[str] = None
@validator('ids', pre=True)
def split_ids(cls, v):
if v is None:
return []
return [int(id.strip()) for id in v.split(",")]
@app.get("/items/")
async def read_items(params: ItemQueryParams = Depends()):
return {"ids": params.ids}这里我们创建了一个继承自 BaseModel 的 ItemQueryParams 类,其中包含一个可选的 ids 字段。我们使用 @validator 装饰器为该字段添加一个预处理验证器,在验证之前将逗号分隔的字符串分割并转换为整数列表。在路由函数中,我们将 ItemQueryParams 作为依赖项注入,FastAPI 会自动解析查询参数并创建模型实例。
方法三:直接在路由函数中使用类型转换
对于简单的场景,我们可以直接在路由函数中进行类型转换。
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(ids: str = Query(None)):
if ids is None:
return {"ids": []}
try:
id_list = [int(id.strip()) for id in ids.split(",")]
return {"ids": id_list}
except ValueError:
return {"error": "Invalid ID format. Please use comma-separated integers."}这种方法直接在路由函数中接收逗号分隔的字符串,然后进行分割和类型转换。虽然简单直接,但缺乏依赖项和 Pydantic 模型的灵活性与可重用性。
方法四:使用 FastAPI 的自定义参数解析
FastAPI 允许我们通过自定义参数解析逻辑来处理复杂的参数类型。
from typing import Any, List
from fastapi import FastAPI, Query, params
app = FastAPI()
class CommaSeparatedList:
def __init__(self, type_: Any):
self.type_ = type_
def __call__(self, value: str) -> List[Any]:
if value is None:
return []
return [self.type_(item.strip()) for item in value.split(",")]
@app.get("/items/")
async def read_items(
ids: List[int] = Query(None, ..., convert_underscores=False)
):
# 注意:这里需要使用自定义的解析逻辑
# 上面的示例仅展示了类型注解,实际解析需要在依赖项中完成
# 以下是简化的处理逻辑
if isinstance(ids, str):
ids = [int(id.strip()) for id in ids.split(",")]
return {"ids": ids}这里我们定义了一个 CommaSeparatedList 类,它可以包装任何类型并将逗号分隔的字符串转换为该类型的列表。不过,这种方法需要更复杂的配置才能与 FastAPI 的查询参数系统完美集成,通常需要结合依赖项使用。
最佳实践与推荐
可重用性:如果需要多次解析逗号分隔的参数,推荐使用依赖项或 Pydantic 模型,这样可以避免代码重复。
错误处理:确保在解析过程中进行适当的错误处理,向客户端返回有意义的错误信息。
文档化:使用 FastAPI 的文档工具自动生成 API 文档,确保客户端了解如何正确传递参数。
性能考虑:对于高并发场景,选择性能较好的解析方法,避免不必要的计算开销。
总结
在 FastAPI 中解析逗号分隔的多个 Query 参数有多种方法可供选择。依赖项和 Pydantic 模型提供了更好的可维护性和可重用性,适合复杂的应用场景;而直接在路由函数中处理则更简单直接,适用于简单的需求。根据项目的具体情况选择合适的方法,可以使代码更加清晰、健壮和易于维护。