Pydantic/SQLAlchemy: 如何使用枚举?

Pydantic/SQLAlchemy: How to work with enums?

如果包含枚举字段,将 sqlalchemy 模型转换为 pydantic 模式(模型)的最佳方法是什么?

SQLalchemy

import enum
from sqlalchemy import Enum, Column, String
from sqlalchemy.orm import declarative_base

Base = declarative_base()

class StateEnum(enum.Enum):
    CREATED = 'CREATED'
    UPDATED = 'UPDATED'

class Adapter(Base):
    __tablename__ = 'adapters'
    id = Column(String, primary_key=True)
    friendly_name = Column(String(256), nullable=False)
    state: StateEnum = Column(Enum(StateEnum))

风靡一时

from pydantic import BaseModel
from enum import Enum

class StateEnumDTO(str, Enum):
    CREATED = 'CREATED'
    UPDATED = 'UPDATED'


class AdapterDTO(BaseModel):
    friendly_name: str
    state: StateEnumDTO  # This currently cannot be converted?

    class Config:
        allow_population_by_field_name = True
        orm_mode = True
        use_enum_values = True

转化

AdapterDTO.from_orm(Adapter(friendly_name='test', state=StateEnum.CREATED))

这会导致错误

value is not a valid enumeration member; permitted: 'CREATED', 'UPDATED' (type=type_error.enum; enum_values=[<StateEnumDTO.CREATED: 'CREATED'>, <StateEnumDTO.UPDATED: 'UPDATED'>])

我该如何配置

a.) 使用 from_orm 方法序列化?

b.) state 字段的创建?

c.) 如何反过来转换?

是否有使用 pydantic 的本机方法或通常如何完成?

更新: 测试用例

def test_enum_conversion_to_dto():
    adapter = Adapter(id='1', friendly_name='test', state=StateEnum.CREATED)
    adapter_dto = AdapterDTO.from_orm(adapter)
    assert adapter_dto.state == StateEnumDTO.CREATED
    assert adapter_dto.state.value == StateEnum.CREATED.value

您必须添加 arbitrary_types_allowed = True 到模型配置 class.

from pydantic import BaseModel
from enum import Enum

class StateEnumDTO(str, Enum):
    CREATED = 'CREATED'
    UPDATED = 'UPDATED'


class AdapterDTO(BaseModel):
    friendly_name: str
    state: StateEnumDTO  # This currently cannot be converted?

    class Config:
        allow_population_by_field_name = True
        orm_mode = True
        use_enum_values = True
        arbitrary_types_allowed = True

Pydantic 要求两个枚举 类 具有相同的类型定义。

在您的例子中,StateEnum 继承自 enum.Enum,但 StateEnumDTO 继承自 strenum.Enum

您可以通过更改 SQLAlchemy 枚举定义来解决此问题:

class StateEnum(str, enum.Enum):
    CREATED = 'CREATED'
    UPDATED = 'UPDATED'