Sqlalchemy数据库int到python枚举

时间:2015-08-29 14:46:32

标签: python sqlalchemy

我现有的数据库中有很多整数,表示枚举。在我的python项目中,我创建了相应的枚举:

class Status(Enum):
    OK = 0
    PENDING = 1
    CANCELED = 2
    DUPLICATE = 3
    INCOMING = 4
    BLOCKED = 5

在我的SQLalchemy模型中,我希望能够执行以下操作

status = Column(Status, nullable=False)

哪个应该将数据库整数转换为python枚举并反向传输

到目前为止,我已尝试从sqlalchemy.types.TypeDecorator继承并覆盖process_bind_param和process_result_value以向前和向后转换int。

但这意味着我必须为违反DRY原则的每个Enum重复此操作。

因此我更喜欢一个继承sqlalchemy.types.TypeDecorator的Mixin类,并覆盖两个方法来转换和继承此mixin的Enum。

有关如何处理此事的任何想法?

1 个答案:

答案 0 :(得分:4)

TypeDecorator可以简单地将枚举类型作为参数。

class EnumAsInteger(sqlalchemy.types.TypeDecorator):
    """Column type for storing Python enums in a database INTEGER column.

    This will behave erratically if a database value does not correspond to
    a known enum value.
    """
    impl = sqlalchemy.types.Integer # underlying database type

    def __init__(self, enum_type):
        super(EnumAsInteger, self).__init__()
        self.enum_type = enum_type

    def process_bind_param(self, value, dialect):
        if isinstance(value, self.enum_type):
            return value.value
        raise ValueError('expected %s value, got %s'
            % (self.enum_type.__name__, value.__class__.__name__))

    def process_result_value(self, value, dialect):
        return self.enum_type(value)

    def copy(self, **kwargs):
        return EnumAsInteger(self.enum_type)


class MyTable(Base):
    status = sqlalchemy.Column(EnumAsInteger(Status), nullable=False)

您可能需要考虑的一件事是如何处理数据库中的未知枚举值。当看到这样的值时,上述解决方案只会抛出ValueError,例如在查询期间。