游戏引擎为我提供了一个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查询的只读属性。这是可能的,如果,如何?
答案 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
类型。