提问人:Amin Ba 提问时间:4/28/2023 最后编辑:ChrisAmin Ba 更新时间:8/11/2023 访问量:2124
如何使用 Python 的枚举和 FastAPI 做出不区分大小写的选择?
How to make case insensitive choices using Python's enum and 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
或返回“Hello World”curl http://127.0.0.1:8001/?q=cd
但这些中的任何一个
curl http://127.0.0.1:8001/?q=aB
curl http://127.0.0.1:8001/?q=AB
curl http://127.0.0.1:8001/?q=Cd
- 等
返回,这是有道理的。422Unprocessable Entity
如何使此验证不区分大小写?
答:
您可以通过重写 's _missing_
方法使值不区分大小写。根据文档,这个类方法(默认情况下不执行任何操作)可用于查找 ;因此,允许人们尝试通过 找到枚举成员。enum
Enum
cls
value
请注意,在声明枚举类时,可以从类扩展(例如,),这将指示枚举中的所有成员都必须具有指定类型的值(例如,)。这也允许将字符串与枚举成员进行比较(使用相等运算符),而不必在枚举成员上使用属性(例如, )。否则,如果枚举类被声明为(没有子类),则需要使用枚举成员的属性(例如,)来安全地将枚举成员与字符串进行比较。str
class MyEnum(str, Enum)
str
==
value
if member.lower() == value
class MyEnum(Enum)
str
value
if member.value.lower() == value
另请注意,除非类的枚举值也包含大写(或大写和小写字母的组合),否则不需要在枚举成员上调用该函数。因此,对于下面的示例,如果只使用小写字母,您可以避免使用它,而只是用于将枚举成员与值进行比较;因此,您可以避免对类中的每个成员调用函数。lower()
if member == value
lower()
例
from enum import Enum
class MyEnum(str, Enum):
ab = 'ab'
cd = 'cd'
@classmethod
def _missing_(cls, value):
value = value.lower()
for member in cls:
if member.lower() == value:
return member
return None
示例(在 Python 3.11+ 中)
在 Python 3.11+ 中,可以改用新引入的 StrEnum
,它允许使用 auto()
功能,从而将成员名称的小写版本作为值。
from enum import StrEnum, auto
class MyEnum(StrEnum):
AB = auto()
CD = auto()
@classmethod
def _missing_(cls, value):
value = value.lower()
for member in cls:
if member == value:
return member
return None
评论
def _missing_(cls, value): for member in cls: if member.value.lower() == value.lower(): return member
.lower()
member.value
== value.lower()
for loop
.lower()
MyEnum(str, enum.Enum)
(str, Enum)
value
if member.lower() == value
value
MyEnum
str
str
member.value.lower()
member.lower()
我真的很喜欢公认的答案的建议,但是它可以简化一点(和概括):
class CaseInsensitiveEnum(str, Enum):
@classmethod
def _missing_(cls, value: str):
for member in cls:
if member.lower() == value.lower():
return member
return None
class MyEnum(CaseInsensitiveEnum):
ab = 'ab'
cd = 'cd'
正如之前的评论中所建议的,它可以通过两种方式进行优化:
member.lower()
如果所有枚举值都将指定为小写,则不需要value.lower()
可以在 for 循环之外执行一次
评论