如何使用 Pony ORM 存储 Python 枚举? [英] How can I store a Python Enum using Pony ORM?

查看:73
本文介绍了如何使用 Pony ORM 存储 Python 枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在这里有这个简单的小 Pony ORM 映射.内置的 Enum 类是 Python 3.4 中的新类,并已向后移植到 2.7.

Say I've got this simple little Pony ORM mapping here. The built-in Enum class is new as of Python 3.4, and backported to 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)

当我运行程序时,抛出一个错误.

When I run the program, an error is thrown.

TypeError: No database converter found for type <enum 'State'>

发生这种情况是因为 Pony 不支持映射枚举类型.当然,这里的解决方法是只存储 Enum 值,并在 Class StateTable 中提供一个 getter 将值再次转换为 Enum.但这既乏味又容易出错.我也可以只使用另一个 ORM.如果这个问题变得太令人头疼,也许我会.但如果可以的话,我宁愿和 Pony 在一起.

This happens because Pony doesn't support mapping the enum type. Of course, the workaround here is to just store the Enum value, and provide a getter in Class StateTable to convert the value to the Enum once again. But this is tedious and error prone. I can also just use another ORM. Maybe I will if this issue becomes too much of a headache. But I would rather stick with Pony if I can.

我更愿意创建一个数据库转换器来存储枚举,就像错误消息所暗示的那样.有人知道怎么做吗?

I would much rather create a database converter to store the enum, like the error message is hinting at. Does anyone know how to do this?

更新:感谢 Ethan 的帮助,我想出了以下解决方案.

UPDATE: Thanks to Ethan's help, I have come up with the following solution.

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))

推荐答案

摘自一些随机邮件列表:

2.2.转换器方法

每个转换器类应该定义以下方法:

Each converter class should define the following methods:

class MySpecificConverter(Converter):

    def init(self, kwargs):
        # Override this method to process additional positional
        # and keyword arguments of the attribute

       if self.attr is not None:
            # self.attr.args can be analyzed here
            self.args = self.attr.args

        self.my_optional_argument = kwargs.pop("kwarg_name")
        # You should take all valid options from this kwargs
        # What is left in is regarded as unrecognized option

    def validate(self, val):
        # convert value to the necessary type (e.g. from string)
        # validate all necessary constraints (e.g. min/max bounds)
        return val

    def py2sql(self, val):
        # prepare the value (if necessary) to storing in the database
        return val

    def sql2py(self, value):
        # convert value (if necessary) after the reading from the db
        return val

    def sql_type(self):
        # generate corresponding SQL type, based on attribute options
        return "SOME_SQL_TYPE_DEFINITION"

您可以研究现有转换器的代码,看看这些方法如何已实施.

You can study the code of the existing converters to see how these methods are implemented.

这篇关于如何使用 Pony ORM 存储 Python 枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆