爲了跟蹤我的一些Django項目模型,我需要實現一個有限狀態機器。我已經有一個類似的應用程序,但它與其他應用程序模型密切相關,不能以任何方式重用。所以我決定重新考慮它。需要一些關於爲Django編寫可重用應用程序的建議
幾個小時後,這是我想出了:
class StateMachine(models.Model):
name = models.CharField(max_length=50, help_text="Must be an unique name")
template = models.BooleanField(default=True)
current_state = models.ForeignKey('State', blank=True, null=True, related_name='current_state')
initial_state = models.ForeignKey('State', blank=True, null=True, related_name='initial_state')
def get_valid_actions(self):
return Action.objects.filter(machine=self, from_state=self.current_state)
def copy(self):
...
class State(models.Model):
name = models.CharField(max_length=50)
machine = models.ForeignKey(StateMachine)
def enter_hook(self, machine=None, action=None, state=None):
pass
def exit_hook(self, machine=None, action=None, state=None):
pass
def _copy(self, machine):
...
class Action(models.Model):
name = models.CharField(max_length=50)
machine = models.ForeignKey(StateMachine)
from_state = models.ForeignKey(State, related_name='from_state')
to_state = models.ForeignKey(State, blank=True, null=True, related_name='to_state')
def is_valid(self):
if self.machine.current_state == self.from_state:
return True
else:
return False
def act(self):
if self.is_valid():
self.from_state.exit_hook(machine=self.machine, action=self, state=self.from_state)
self.machine.current_state = self.to_state
self.machine.save()
self.to_state.enter_hook(machine=self.machine, action=self, state=self.to_state)
else:
raise ActionNotApplicable()
return self.machine
def _copy(self, machine):
...
我很滿意的結果。它完成狀態機所要做的事情,而不是別的。在我的模型,我使用它是這樣的:
class SampleModel(models.Model):
machine = models.ForeignKey(StateMachine, null=True)
def setup_machine(self):
self.machine = StateMachine.objects.get(template=True, name='bla bla bla').copy()
self.save()
我基本上使用管理界面創建一個「模板」的機器,然後我運行的複製狀態機模型,並設置該模板爲False複製方法。
現在,這纔是我的問題:)
是利用相同的SampleModel一個ForeignKey附加 的的StateMachine它的最佳方式?我讀過關於Django中的泛型關係的 ,但我以前從未使用過 。在我的情況下使用它會有好處嗎?
我試圖遵循「做一件事 並把它做好」的理念, 但我有其他業務 需求來實現。例如,對於 示例,每次狀態發生更改時,我都需要發送一封電子郵件給特定的組,並且此組的狀態各不相同。我提出的第一個解決方案是在狀態模型中添加一個「email」字段。但是這會違反這個應用程序要做的事情,這只是爲了跟蹤狀態機。解決這個問題最好的辦法是什麼?
我還包括在 模型一些鉤子函數,這樣後來有人可能 將自定義的行爲,這是 做到這一點的最好方法是什麼? (我認爲 Django已經是一個信號系統)
其他的想法/評論?我是新來 這種可重複使用的應用程序的事情:)
謝謝!
我想在我的情況下,在數據庫中存儲所有內容是必要的。瞭解國家有幫助,但並不能解決我所有的問題。例如,我想能夠將特定狀態鏈接到用戶,以便用戶在狀態更改時接收更新。 – 2010-07-15 15:06:14
我認爲它不會改變任何事情:檢查我的編輯... – sebpiq 2010-07-15 15:38:15
謝謝!我會檢查代碼:) – 2010-07-15 20:14:23