使用只读列获取相同值的只读属性

时间:2017-01-29 16:49:22

标签: python python-3.x sqlalchemy

游戏引擎为我提供了一个Player类,其具有uniqueid只读属性来识别玩家。我想将其“转换”为SQLAlchemy的Column,以便我可以像这样查询玩家:

query = session.query(Player).filter(Player.uniqueid=='STEAM_0:0:1234567')
player = query.one_or_none()
if player is None:
    player = Player(uniqueid='STEAM_0:0:1234567')

以下是我班级目​​前的情况:

class Player(game.Player, db.Model):
    _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False)

    def __init__(self, index, **kwargs):
        game.Player.__init__(index)  # initializes uniqueid
        db.Model.__init__(_uniqueid=self.uniqueid, **kwargs)

接下来我想为_uniqueid创建一个只读界面,因此API用户无法再写入变量(嗯,他们可以通过_uniqueid,但这是他们的责任因为访问它应该通过非私人uniqueid)发生。

我想用新的覆盖原来的uniqueid

@property
def uniqueid(self):
    return self._uniqueid

这是只读的并且“隐藏”原始的_uniqueid,阻止任何人写入它,除非他们故意访问私有的(我甚至不会在文档中列出它,我只会公开非私人的)。

唯一的问题是,完全会覆盖旧的,这意味着__init__的{​​{1}}因_uniqueid=self.uniqueid使用self.uniqueid而无效新的 getter,而不是旧的。

总结一下,我想要的是将只读属性转换为可用于使用SQLAlchemy查询的只读属性。这是可能的,如果,如何?

1 个答案:

答案 0 :(得分:1)

您可以使用super访问game.Player的媒体资源。我们可以使用Cython创建的简单C扩展类型进行测试:

# game.pyx
cdef class Player:
    cdef int index;

    def __init__(self, index):
        self.index = index

    @property
    def uniqueid(self):
        return "foo"


# test.py
class Player(game.Player, Base):
    __tablename__ = "player"

    id = Column(Integer, primary_key=True)
    _uniqueid = Column('uniqueid', String(21), unique=True, nullable=False)

    def __init__(self, index, **kwargs):
        game.Player.__init__(self, index)  # initializes uniqueid
        Base.__init__(self, _uniqueid=super().uniqueid, **kwargs)

    @property
    def uniqueid(self):
        return self._uniqueid

print(Player(1).uniqueid)  # "foo"

由于从C扩展类型继承的不稳定性,这可能会或可能不会起作用,具体取决于game.Player类型使用的C魔法。

此外,由于ORM在从数据库加载实例时会绕过__init__,因此您必须挂钩load事件才能初始化game.Player类型。