SQLAlchemy是否支持这样的操作:
class Character(Base):
__tablename__ = 'character'
id = Column(Integer, primary_key=True)
level = Column(Integer)
@ColumnProperty(Integer)
def xp(self):
return self._xp
@xp.setter
def xp(self, value):
self._xp = value
while self._xp >= self.xp_to_level_up():
self.level += 1
self._xp -= 100
def __init__(self, level=0, xp=0):
self.level = level
self._xp = xp
其中id
, level
和xp
将被存储到数据库中。所以基本上是一个Column
,但不是一个属性,而是一个属性。
只需添加一个_xp
列定义,它映射到表中的xp
列,并使用一个常规的@property
对象来实现您的setter逻辑:
class Character(Base):
__tablename__ = 'character'
id = Column(Integer, primary_key=True)
level = Column(Integer)
_xp = Column('xp', Integer)
def __init__(self, level=0, xp=0):
self.level = level
self._xp = xp
@property
def xp(self):
return self._xp
@xp.setter
def xp(self, value):
self._xp = value
while self._xp >= self.xp_to_level_up():
self.level += 1
self._xp -= 100
参见与属性名区分命名列。
上面将实例上的_xp
属性存储为character
表中的xp
,但是您的代码使用Character.xp
属性间接地读写_xp
的值。
也可以使用@hybrid_property
;这就像上面使用的property
一样,但也允许您在查询过滤器中使用Character.xp
:
from sqlalchemy.ext.hybrid import hybrid_property
class Character(Base):
__tablename__ = 'character'
id = Column(Integer, primary_key=True)
level = Column(Integer)
_xp = Column('xp', Integer)
def __init__(self, level=0, xp=0):
self.level = level
self._xp = xp
@hybrid_property
def xp(self):
return self._xp
@xp.setter
def xp(self, value):
self._xp = value
while self._xp >= self.xp_to_level_up():
self.level += 1
self._xp -= 100
现在您可以使用session.query(Character).filter(Character.xp > 42)
和其他类似的过滤查询,而不必使用Character._xp
。
如果你想对你的字符进行批量更新,你可能必须包含一个update_expression
实现,它将告诉SQLAlchemy如何为UPDATE
生成SET
表达式;也许使用CASE
表达式来处理更新关卡,除了调整XP。