有什么方法可以将 FastAPI 处理程序的输入参数限制为几个指定的选项?

Any way to limit the input arguments of a FastAPI handler into several specified options?

我想知道是否有什么方法可以让我轻松处理输入参数并将它们限制为 FASTAPI 中的多个值。

例如,如果我在这里有一个 hello-world 处理程序:

from fastapi import FastAPI

app = FastAPI()

@app.get(/)
async def root(name:str):
    return {"user_name_is": name}

而我想实现的是,让用户只能输入以下名称之一作为参数[BobJack],其他名称都是非法的。

再写一些检查代码来达到预期的结果并不复杂:

from fastapi import FastAPI

app = FastAPI()

@app.get(/)
async def root(name:str):
    if name in ['Bob' , 'Jack']:
         return {"user_name_is": name}
    else:
         raise HTTPException(status_code=403)

然而,编写代码仍然不够容易,尤其是当需要处理大量输入参数时。我想知道是否有一种方法可以使用类型提示和 pydantic 来获得相同的结果?

在文档中找不到太多信息,需要帮助,谢谢。

=======

顺便说一句,如果我还需要获取输入参数列表,有没有办法检查所有参数,就像下面的代码一样?

from fastapi import FastAPI
from typing import List

app = FastAPI()

@app.get(/)
async def root(names:List[str]):
    for name in names:
        if name not in ['Bob','Jack']:
            raise ...
    # else ,check passed
    return {"user_name_is": name}

您正在寻找 Pydantic 的 @validator

参见:https://pydantic-docs.helpmanual.io/usage/validators

from pydantic import BaseModel, validator
from typing import List
from fastapi import FastAPI, Depends


app = FastAPI()


class Names(BaseModel):
    names: List[str]

    @validator("names", pre=True, always=True)
    def check_allowed_names(cls, v):
        allowed_names = ["Billie", "Joe"]
        for name in v:
            if name not in allowed_names:
                raise ValueError(f"Name {name} is not allowed")

        return v


@app.post("/")
async def root(names: Names):
    return {"user_name_is": names.names}


使用Enumhttps://fastapi.tiangolo.com/tutorial/path-params/?h=enum#predefined-values

from enum import Enum

import uvicorn
from fastapi import FastAPI


class Names(str, Enum):
    Bob = "Bob"
    Jack = "Jack"


app = FastAPI()


@app.get("/")
async def root(name: Names):
    return {"user_name_is": name}

我知道这个问题已经有一个答案被接受,但我觉得最干净的方法是使用 Literal 这样的输入:

from fastapi import FastAPI
from typing import Literal

app = FastAPI()

@app.get("/{name}")
async def root(name: Literal["Bob", "Jack"]):
    return {"user_name_is": name}