API 应提供一个端点,用户可以在其中提供
guid
、path
或 code
。 url 方案应该是这样的:
api/locations?code={str}&guid={str}&path={str}
当前代码如下:
@router.get("/api/locations")
def get_functional_locations(
guid: Optional[str] = None,
code: Optional[str] = None,
path: Optional[str] = None,
) -> Union[List[Locations], PlainTextResponse]:
if guid:
return ...
if path:
return ...
if code:
return ...
return PlainTextResponse(status_code=status.HTTP_400_BAD_REQUEST)
是否有另一种方法来提供多个可选参数并进行异或运算,只允许用户只填写一个参数?
首先,我想问,如果你有三个互斥的参数,并且都是获取相同信息的方法,那不应该是三个不同的端点,例如
api/locations/guid/{guid}
,api/locations/code/{code}
和api/locations/path/{path}
?通常最好有几个较小的函数来做一件事。
如果您确实想要这个,您可以随时为其编写自己的代码,例如使用类作为依赖项,这里与pydantic根验证器
一起使用from fastapi import Depends, HttpException
from pydantic import BaseModel, root_validator
class Params(BaseModel):
guid: str | None = None
code: str | None = None
path: str | None = None
@root_validator
def validate(cls, values):
if len([val for val in values.values() if val is not None]) != 1:
raise HTTPException(400, "Exactly one of guid, code, and path must be provided")
return values
@app.get("/api/locations")
def foo(params: Params = Depends()):
...
您可以使用dependency,这是一个可以采用端点可以采用的所有相同参数的函数。在依赖函数内,您可以执行所需的检查,以确保用户仅提供了“仅一个”可选参数。如果是这样,请将字典返回给端点,包括参数及其值,这可以帮助您找到客户端使用了哪个参数(及其值)。否则,如果提供了多个参数的值,您可以引发 HTTPException
,通知用户应用于该端点的限制。请注意,下面的示例使用
Optional
模块中的
typing
关键字(如您问题中提供的示例所示)来声明可选参数。然而,在 Python 3.10+ 中,也可以使用,例如,guid: str | None = None
。无论哪种情况,使参数可选的最重要部分是
= None
部分。请查看这个答案和这个答案以查找更多详细信息以及在 FastAPI 中使参数可选的所有可用选项。 工作示例
from fastapi import FastAPI, Depends, HTTPException
from typing import Optional
app = FastAPI()
def params(
guid: Optional[str] = None,
code: Optional[str] = None,
path: Optional[str] = None,
):
if sum(i is not None for i in [guid, code, path]) != 1:
raise HTTPException(400, 'Please provide only one of either guid, code or path')
else:
return {'guid': guid, 'code': code, 'path': path}
@app.get('/')
def main(d: dict = Depends(params)):
for k, v in d.items():
if v:
return {k: v}