Django FSM 状态转换错误
Django FSM state transition error
from datetime import datetime
from django.db import models
from django_fsm import FSMField, transition
class Network(models.Model):
name = models.CharField(max_length=100, unique=True)
prefix = models.CharField(max_length=20, default='')
country = models.CharField(max_length=50, default='')
client_wsdl = models.TextField(blank=True, default='')
class Meta:
db_table = 'network'
def __unicode__(self):
return u'{0}'.format(self.name)
class SmsMessage(models.Model):
#Define State Machine
received, started, failed, submitted, completed = "received", "started", "failed", "submitted", "completed"
STATE_CHOICES = (
(received, received),
(started, started),
(failed, failed),
(submitted, submitted),
(completed, completed),
)
message_id = models.CharField(max_length=50)
sender_id = models.CharField(max_length=50, default='')
msisdn = models.CharField(max_length=50)
message = models.CharField(max_length=200)
priority = models.CharField(max_length=50)
status = models.CharField(max_length=20, default='')
state = FSMField(default=received, choices=STATE_CHOICES, protected=True)
callback = models.CharField(max_length=200, default='')
network = models.ForeignKey(Network, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'sms_message'
def __unicode__(self):
return self.message_id
@transition(field=state, source='received', target=started)
def started(self):
'''
Change message request to started state.
'''
return
@transition(field=state, source='started', target=failed)
def failed(self):
'''
For started requests that cannot be submitted to Network
hence in a failed state.
'''
return
@transition(field=state, source=started, target=submitted)
def submitted(self):
'''
Change message request to submitted state.
'''
return
@transition(field=state, source='submitted', target=completed)
def completed(self):
'''
Request was sucessfully submited to mno and a response returned.
'''
return
根据我上面的代码,提交的状态转换失败并出现此错误:
Traceback (most recent call last):
worker_1 | File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 240, in trace_task
worker_1 | R = retval = fun(*args, **kwargs)
worker_1 | File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 438, in __protected_call__
worker_1 | return self.run(*args, **kwargs)
worker_1 | File "/app/sms_platform/apps/api/tasks.py", line 176, in run
worker_1 | return self._send_sms(msisdn, message, request_id, correlation_id, mno, sender_id, pk=pk)
worker_1 | File "/app/sms_platform/apps/api/tasks.py", line 126, in _send_sms
worker_1 | sms_obj.submitted()
worker_1 | File "/usr/local/lib/python2.7/dist-packages/django_fsm/__init__.py", line 512, in _change_state
worker_1 | return fsm_meta.field.change_state(instance, func, *args, **kwargs)
worker_1 | File "/usr/local/lib/python2.7/dist-packages/django_fsm/__init__.py", line 304, in change_state
worker_1 | object=instance, method=method)
worker_1 | TransitionNotAllowed: Can't switch from state 'started' using method 'submitted'
唯一的区别是在转换源中提交的文件不像其他文件那样被引用。否则,如果我引用 'submitted',它可以正常工作。
对此感到困惑,因为所有状态都在 class 的开头定义。
更新:
您可以像这样在单独的 class 中定义您的状态。
class StateSmsMessage(object):
RECEIVED = 'received'
STARTED = 'started'
...
CHOICES = (
(RECEIVED, RECEIVED),
(STARTED, STARTED),
...
)
然后在过渡装饰器中使用 StateSmsMessage.STARTED
。
您将 started
变量重新定义为方法名称的问题
class SmsMessage(models.Model)
... started, ...= ... "started", ...
@transition(field=state, source='received', target=started)
def started(self): # <- LOL
....
@transition(field=state, source=started, target=submitted)
def submitted(self):
....
>>> print(SmsMessage.started)
<unbound method SmsMessage.started>
from datetime import datetime
from django.db import models
from django_fsm import FSMField, transition
class Network(models.Model):
name = models.CharField(max_length=100, unique=True)
prefix = models.CharField(max_length=20, default='')
country = models.CharField(max_length=50, default='')
client_wsdl = models.TextField(blank=True, default='')
class Meta:
db_table = 'network'
def __unicode__(self):
return u'{0}'.format(self.name)
class SmsMessage(models.Model):
#Define State Machine
received, started, failed, submitted, completed = "received", "started", "failed", "submitted", "completed"
STATE_CHOICES = (
(received, received),
(started, started),
(failed, failed),
(submitted, submitted),
(completed, completed),
)
message_id = models.CharField(max_length=50)
sender_id = models.CharField(max_length=50, default='')
msisdn = models.CharField(max_length=50)
message = models.CharField(max_length=200)
priority = models.CharField(max_length=50)
status = models.CharField(max_length=20, default='')
state = FSMField(default=received, choices=STATE_CHOICES, protected=True)
callback = models.CharField(max_length=200, default='')
network = models.ForeignKey(Network, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'sms_message'
def __unicode__(self):
return self.message_id
@transition(field=state, source='received', target=started)
def started(self):
'''
Change message request to started state.
'''
return
@transition(field=state, source='started', target=failed)
def failed(self):
'''
For started requests that cannot be submitted to Network
hence in a failed state.
'''
return
@transition(field=state, source=started, target=submitted)
def submitted(self):
'''
Change message request to submitted state.
'''
return
@transition(field=state, source='submitted', target=completed)
def completed(self):
'''
Request was sucessfully submited to mno and a response returned.
'''
return
根据我上面的代码,提交的状态转换失败并出现此错误:
Traceback (most recent call last):
worker_1 | File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 240, in trace_task
worker_1 | R = retval = fun(*args, **kwargs)
worker_1 | File "/usr/local/lib/python2.7/dist-packages/celery/app/trace.py", line 438, in __protected_call__
worker_1 | return self.run(*args, **kwargs)
worker_1 | File "/app/sms_platform/apps/api/tasks.py", line 176, in run
worker_1 | return self._send_sms(msisdn, message, request_id, correlation_id, mno, sender_id, pk=pk)
worker_1 | File "/app/sms_platform/apps/api/tasks.py", line 126, in _send_sms
worker_1 | sms_obj.submitted()
worker_1 | File "/usr/local/lib/python2.7/dist-packages/django_fsm/__init__.py", line 512, in _change_state
worker_1 | return fsm_meta.field.change_state(instance, func, *args, **kwargs)
worker_1 | File "/usr/local/lib/python2.7/dist-packages/django_fsm/__init__.py", line 304, in change_state
worker_1 | object=instance, method=method)
worker_1 | TransitionNotAllowed: Can't switch from state 'started' using method 'submitted'
唯一的区别是在转换源中提交的文件不像其他文件那样被引用。否则,如果我引用 'submitted',它可以正常工作。
对此感到困惑,因为所有状态都在 class 的开头定义。
更新:
您可以像这样在单独的 class 中定义您的状态。
class StateSmsMessage(object):
RECEIVED = 'received'
STARTED = 'started'
...
CHOICES = (
(RECEIVED, RECEIVED),
(STARTED, STARTED),
...
)
然后在过渡装饰器中使用 StateSmsMessage.STARTED
。
您将 started
变量重新定义为方法名称的问题
class SmsMessage(models.Model)
... started, ...= ... "started", ...
@transition(field=state, source='received', target=started)
def started(self): # <- LOL
....
@transition(field=state, source=started, target=submitted)
def submitted(self):
....
>>> print(SmsMessage.started)
<unbound method SmsMessage.started>