Sqlalchemy database int to python enum

狂风中的少年 提交于 2021-02-19 06:55:27

问题


I have lots of integers in my existing database which signify an enum. In my python project I have created the corresponding enums like so:

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

In my SQLalchemy models I'd like to be able to do the following

status = Column(Status, nullable=False)

Which should convert the database integers to python enums and back transparantly

So far I've tried to inherit from the sqlalchemy.types.TypeDecorator and overwrite the process_bind_param and process_result_value to cast the int back and forwards.

This would however mean I would have to repeat this for every Enum in violation of the DRY principle.

I would thus prefer a Mixin class which inherits sqlalchemy.types.TypeDecorator and overwrites the two methods to cast to and from the Enum which inherits this mixin.

Any ideas on how to approach this?


回答1:


The TypeDecorator can simply take the enum type as an argument.

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)

One thing you may need to consider is how to deal with unknown enum values in the database. The above solution will simply throw ValueError when such values are seen, e.g. during a query.



来源:https://stackoverflow.com/questions/32287299/sqlalchemy-database-int-to-python-enum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!