Not answering the question directly, but it's related.
If you want to bind an enum to a pydantic model without relying on its value
, you can create an enum on the fly. (Python >= 3.11) This works with FastAPI and the generated OpenAPI schema will reflect it properly.
class Group(Enum):
user = 0
manager = 1
admin = 2
group_enum_names = Enum("GroupEnumNames", [(g.name, g.name) for g in Group])
class User(BaseModel):
id: int
username: str
group: group_enum_names
# works
print(User(**{"id": 5, "username": "admin", "group": "admin"}))
# yields {"id":5,"username":"admin","group":"admin"}
# does not work, there are no ties to the original enum anymore
print(User(**{"id": 5, "username": "admin", "group": 1}))
# yields pydantic_core._pydantic_core.ValidationError
And to map back to the original Group
enum:
user = User(**{"id": 5, "username": "admin", "group": "admin"})
group = Group[user.group.name]
Arguably, some logic to could be added directly into the User
model to handle that.
Note: mypy 1.6.1 does not like that solution and yields Second argument of Enum() must be string, tuple, list or dict literal for mypy to determine Enum members [misc]
over the dynamically created enum, even if the second argument is a tuple.
Tested with:
- pydantic v2.4.2
- fastapi v0.103.0