假设我在这里有这个简单的小 Pony ORM 映射。内置的 Enum 类是 Python 3.4 的新内容,并向后移植到 2.7。
from enum import Enum
from pony.orm import Database, Required
class State(Enum):
ready = 0
running = 1
errored = 2
if __name__ == '__main__':
db = Database('sqlite', ':memory:', create_db=True)
class StateTable(db.Entity):
state = Required(State)
db.generate_mapping(create_tables=True)
当我运行程序时,会引发错误。
TypeError: No database converter found for type <enum 'State'>
这是因为 Pony 不支持映射枚举类型。当然,这里的解决方法是只存储 Enum 值,并在 Class StateTable 中提供一个 getter 以再次将值转换为 Enum。但这是乏味且容易出错的。我也可以只使用另一个 ORM。如果这个问题变得太令人头疼,也许我会。但如果可以的话,我宁愿坚持使用 Pony。
我宁愿创建一个数据库转换器来存储枚举,就像错误消息暗示的那样。有谁知道如何做到这一点?
更新:感谢 Ethan 的帮助,我想出了以下解决方案。
from enum import Enum
from pony.orm import Database, Required, db_session
from pony.orm.dbapiprovider import StrConverter
class State(Enum):
ready = 0
running = 1
errored = 2
class EnumConverter(StrConverter):
def validate(self, val):
if not isinstance(val, Enum):
raise ValueError('Must be an Enum. Got {}'.format(type(val)))
return val
def py2sql(self, val):
return val.name
def sql2py(self, value):
# Any enum type can be used, so py_type ensures the correct one is used to create the enum instance
return self.py_type[value]
if __name__ == '__main__':
db = Database('sqlite', ':memory:', create_db=True)
# Register the type converter with the database
db.provider.converter_classes.append((Enum, EnumConverter))
class StateTable(db.Entity):
state = Required(State)
db.generate_mapping(create_tables=True)
with db_session:
s = StateTable(state=State.ready)
print('Got {} from db'.format(s.state))