Skip to main content
 首页 » 编程设计

python之Django FSM 状态转换错误

2024年10月24日27arxive

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' 

唯一的区别是在转换源中提交的不像其他的那样被引用。否则,如果我引用“已提交”,它就可以正常工作。

我对此感到困惑,因为所有状态都在类(class)开始时定义。

请您参考如下方法:

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>