2015-11-04 72 views
2
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 

从我上面的代码,提交状态转换失败,此错误:Django的FSM状态转换错误

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' 

的是,在提交的转变源的唯一区别是没有报价和其他人一样。否则,如果我引用“已提交”,它可以正常工作。

我对此感到困惑,因为所有的州都是在班级开始时定义的。

回答

2

,你有started变量redifined方法名

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> 
0

更新:

你可以像这样在一个单独的类中定义你的状态。

class StateSmsMessage(object): 
    RECEIVED = 'received' 
    STARTED = 'started' 
    ... 

    CHOICES = (
     (RECEIVED, RECEIVED), 
     (STARTED, STARTED), 
     ... 
    ) 

,然后在过渡装饰用StateSmsMessage.STARTED

+0

都能跟得上的问题,仍然无法正常工作。将NameError:name'SmsMessage'未定义为错误。 – user1048839

+0

更新的答案.. –

+0

这感觉就像一个圆的方式。什么阻止它使用相同的类变量? – user1048839