You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python的enum与FastAPI实现不区分大小写的选项?

实现FastAPI中Enum查询参数的大小写不敏感验证

问题场景

我有如下FastAPI应用代码:

import enum
from typing import Annotated, Literal

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()


class MyEnum(enum.Enum):
    ab = "ab"
    cd = "cd"


class MyInput(BaseModel):
    q: Annotated[MyEnum, Query(...)]


@app.get("/")
def test(inp: MyInput = Depends()):
    return "Hello world"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()

当使用curl http://127.0.0.1:8001/?q=ab或curl http://127.0.0.1:8001/?q=cd时,可正常返回"Hello World";但使用curl http://127.0.0.1:8001/?q=aB、curl http://127.0.0.1:8001/?q=AB等大小写混合或全大写参数时,会返回422 Unprocessable Entity错误。需要实现该验证的大小写不敏感。

解决方案

方法一:自定义Enum的匹配逻辑

通过重写Enum类的_missing_方法,让枚举在匹配输入值时忽略大小写:

import enum
from typing import Annotated, Literal

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()


class MyEnum(enum.Enum):
    ab = "ab"
    cd = "cd"

    @classmethod
    def _missing_(cls, value):
        # 遍历枚举成员,忽略大小写匹配
        for member in cls:
            if member.value.lower() == value.lower():
                return member
        return None


class MyInput(BaseModel):
    q: Annotated[MyEnum, Query(...)]


@app.get("/")
def test(inp: MyInput = Depends()):
    return "Hello world"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()

该方法利用Enum的_missing_钩子函数,当输入值无法直接匹配枚举成员时,自动执行大小写不敏感的匹配逻辑,返回对应的枚举成员。

方法二:使用Pydantic字段验证器

在Pydantic模型中添加字段验证器,将输入参数统一转为小写后再匹配枚举:

import enum
from typing import Annotated, Literal

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel, field_validator

app = FastAPI()


class MyEnum(enum.Enum):
    ab = "ab"
    cd = "cd"


class MyInput(BaseModel):
    q: Annotated[MyEnum, Query(...)]

    @field_validator('q', mode='before')
    def lowercase_q(cls, v):
        # 转换输入字符串为小写
        if isinstance(v, str):
            return v.lower()
        return v


@app.get("/")
def test(inp: MyInput = Depends()):
    return "Hello world"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()

通过field_validator的mode='before'参数,在字段解析为枚举类型之前,先将输入的字符串转为小写,确保能匹配到对应的枚举成员。

方法三:直接在Query中添加转换逻辑

如果不想修改Enum或Pydantic模型,可以直接在Query参数中指定转换函数:

import enum
from typing import Annotated, Literal

import uvicorn
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()


class MyEnum(enum.Enum):
    ab = "ab"
    cd = "cd"


class MyInput(BaseModel):
    q: Annotated[MyEnum, Query(..., transform=lambda v: v.lower() if isinstance(v, str) else v)]


@app.get("/")
def test(inp: MyInput = Depends()):
    return "Hello world"


def main():
    uvicorn.run("run:app", host="0.0.0.0", reload=True, port=8001)


if __name__ == "__main__":
    main()

利用Query的transform参数,直接对输入的查询参数进行小写转换,逻辑简洁,不影响原有的Enum和模型定义。


内容的提问来源于stack exchange,提问作者Amin Ba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:32:11