Reputation: 21923
Does SQLAlchemy support something like this:
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
Where id
, level
, and xp
would get stored into the database. So basically a Column
but instead of an attribute a property.
Upvotes: 3
Views: 2262
Reputation: 1122132
Just add a _xp
column definition, that maps to the xp
column in the table, and use a regular @property
object to implement your setter logic:
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
See Naming Columns Distinctly from Attribute Names.
The above stores the _xp
attribute on the instance as xp
in the character
table, but your code uses the Character.xp
property to read and write the value of _xp
indirectly.
You can also use a @hybrid_property
; this acts just like property
as used above, but then also lets you use Character.xp
in query filters:
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
Now you can use session.query(Character).filter(Character.xp > 42)
and other such filtering queries, rather than have to use Character._xp
.
If you want to do bulk updates on your characters, you may have to include a update_expression
implementation that would tell SQLAlchemy how to generate a SET
expression for the UPDATE
; perhaps using a CASE
expression to handle updating the level in addition to adjusting XP.
Upvotes: 5