问题
I am using sqlalchemy and flask-sqlalchemy, one of my db model comes with a state column
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(8))
state = db.Column(db.Integer, default=ServerState.IN_PACKAGE, nullable=True)
def init_state(self):
self.state = State1
def transit_state(self):
self.state.next(self)
The problem is that this state column is saved into db as a integer, but in order to implement a proper state machine, it is implemented as a Class:
class State1(BaseState):
__int = 100
__name = 'State1'
@staticmethod
def next(item):
if item.contidition1 is None or item.condition2 is None:
raise InvalidStateTransition
item.state = State2
This works well and keeps the code clean, but the critical issue is that when I want to commit the Item to the db, it surely will give me error :
Incorrect integer value: '<class 'app.models.Item.State1'>' for column 'state' at row 1
So, is there a way for the session, or python, to automatically convert the class to its int representation when save into the db, and convert from the int to its state class when it is retrieved from the db?
回答1:
You can use a TypeDecorator. Something like:
class StateType(TypeDecorator):
impl = Integer
def process_bind_param(self, value, dialect):
return map_integer_to_my_state(value)
def process_result_value(self, value, dialect):
return map_my_state_to_integer(value)
Then you can use StateType
as the type of the state
column:
state = db.Column(StateType, ...)
来源:https://stackoverflow.com/questions/40257478/how-can-sqlalchemy-work-with-custom-class-as-the-attributes