Pytransitions:是否可以更改机器在模型中注入的模型属性?
Pytransitions: Is it possible to change what model attribute the machine injects in the model?
我正在将 pytransitions
状态机改装到现有模型中,该模型恰好已经有一个名为 status
的列(该模型也恰好是 SQLAlchemy 模型)。
我注意到转换库注入了一个 state
字段,但我不确定是否有办法将该字段更改为我模型的 status
列并让转换反映在那个特定的领域。如果目前没有办法,我正在考虑使用 machine.after_state_change
回调并从那里开始工作。
除了 (ab) 使用该特定回调之外,还有什么合适的解决方法?
从 transitions
0.7.1 开始,没有简单的方法来调整模型状态属性的名称。重写 Transition._state_change
、Machine._trigger
和 Machine.is_state
太复杂了,恕我直言。您可以 'alias' 您的状态字段,方法是使用 Model.state
作为 属性:
class Model:
@property
def state(self):
return self.status
@state.setter
def state(self, value):
self.status = value
或者使用 SQLAlchemy 的 :
from sqlalchemy import Column, String, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import synonym, sessionmaker
from transitions import Machine
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)
Base = declarative_base()
class Model(Base):
__tablename__ = 'Model'
id = Column(Integer, primary_key=True, autoincrement=True)
status = Column(String, default='initial')
state = synonym('status')
def __repr__(self):
return "<Model(id='{}', status='{}')>".format(self.id, self.status)
Base.metadata.create_all(engine)
session = Session()
m1 = Model()
m2 = Model()
session.add_all([m1, m2])
m = Machine(model=[m1, m2], states=['A', 'B'], initial='A')
print(session.query(Model).filter_by(status='A').all())
# >>> [<Model(id='1', status='A')>, <Model(id='2', status='A')>]
m1.to_B()
print(session.query(Model).filter_by(status='B').all())
# >>> [<Model(id='1', status='B')>]
从 0.8.3 开始,您可以在机器上指定 model_attribute
。
>>> from transitions import Machine
2 class Matter(object):
3 pass
4
5 lump = Matter()
6 transitions = [
7 { 'trigger': 'melt', 'source': 'solid', 'dest': 'liquid' },
8 { 'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas' },
9 { 'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas' },
10 { 'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma' }
11 ]
12 machine = Machine(
13 model=lump,
14 states=['solid', 'liquid', 'gas', 'plasma'],
15 initial='solid',
16 transitions=transitions,
17 model_attribute='my_state'
18 )
>>> lump.state
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Matter' object has no attribute 'state'
'Matter' object has no attribute 'state'
>>> lump.my_state
'solid'
我正在将 pytransitions
状态机改装到现有模型中,该模型恰好已经有一个名为 status
的列(该模型也恰好是 SQLAlchemy 模型)。
我注意到转换库注入了一个 state
字段,但我不确定是否有办法将该字段更改为我模型的 status
列并让转换反映在那个特定的领域。如果目前没有办法,我正在考虑使用 machine.after_state_change
回调并从那里开始工作。
除了 (ab) 使用该特定回调之外,还有什么合适的解决方法?
从 transitions
0.7.1 开始,没有简单的方法来调整模型状态属性的名称。重写 Transition._state_change
、Machine._trigger
和 Machine.is_state
太复杂了,恕我直言。您可以 'alias' 您的状态字段,方法是使用 Model.state
作为 属性:
class Model:
@property
def state(self):
return self.status
@state.setter
def state(self, value):
self.status = value
或者使用 SQLAlchemy 的
from sqlalchemy import Column, String, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import synonym, sessionmaker
from transitions import Machine
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)
Base = declarative_base()
class Model(Base):
__tablename__ = 'Model'
id = Column(Integer, primary_key=True, autoincrement=True)
status = Column(String, default='initial')
state = synonym('status')
def __repr__(self):
return "<Model(id='{}', status='{}')>".format(self.id, self.status)
Base.metadata.create_all(engine)
session = Session()
m1 = Model()
m2 = Model()
session.add_all([m1, m2])
m = Machine(model=[m1, m2], states=['A', 'B'], initial='A')
print(session.query(Model).filter_by(status='A').all())
# >>> [<Model(id='1', status='A')>, <Model(id='2', status='A')>]
m1.to_B()
print(session.query(Model).filter_by(status='B').all())
# >>> [<Model(id='1', status='B')>]
从 0.8.3 开始,您可以在机器上指定 model_attribute
。
>>> from transitions import Machine
2 class Matter(object):
3 pass
4
5 lump = Matter()
6 transitions = [
7 { 'trigger': 'melt', 'source': 'solid', 'dest': 'liquid' },
8 { 'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas' },
9 { 'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas' },
10 { 'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma' }
11 ]
12 machine = Machine(
13 model=lump,
14 states=['solid', 'liquid', 'gas', 'plasma'],
15 initial='solid',
16 transitions=transitions,
17 model_attribute='my_state'
18 )
>>> lump.state
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Matter' object has no attribute 'state'
'Matter' object has no attribute 'state'
>>> lump.my_state
'solid'