ここに、この単純で小さな 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 値を格納し、値を再度 Enum に変換するクラス StateTable に getter を提供することです。しかし、これは面倒でエラーが発生しやすくなります。別の ORM を使用することもできます。この問題があまりにも頭を悩ませるようになったら、そうするかもしれません。でも、できればポニーを使い続けたいです。
エラーメッセージが示唆しているように、列挙型を格納するデータベースコンバーターを作成したいと思います。誰もこれを行う方法を知っていますか?
更新: 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))