开发人员需要创建一个可复用状态机应用程序,用于跟踪 Django 项目模型中的状态。他们目前使用一个与其他模型紧密耦合且不可复用的应用程序,因此决定重新设计它。
- 解决方案
开发人员提供了他们最初的设计,其中包括StateMachine
、State
和Action
模型。他们还提供了在SampleModel
中使用状态机的方法。
对于第一个问题,关于使用 ForeignKey
将 StateMachine
附加到 SampleModel
是否是最佳方式,答案是肯定的。使用外键是最简单和最直接的方式来建立这两个模型之间的关系。
对于第二个问题,关于如何解决向特定组发送电子邮件的需求,解决方案是创建一个新的模型来处理此任务。该模型可以包含组和电子邮件字段,并且可以在状态更改时触发信号以发送电子邮件。
对于第三个问题,关于是否应该在模型中包含钩子函数,答案是肯定的。钩子函数允许应用程序开发人员在状态更改时附加自定义行为,这是很有用的。
以下是代码示例:
class StateMachine(models.Model):
name = models.CharField(max_length=50, unique=True)
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):
return self.machine.current_state == self.from_state
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 EmailNotification(models.Model):
group = models.ForeignKey(Group)
email = models.EmailField()
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()
def send_email_notifications(self):
for notification in EmailNotification.objects.filter(group=self.current_state.group):
send_email(notification.email, 'State changed to {}'.format(self.current_state.name))
这段代码提供了一个可复用的状态机应用程序,可以用于跟踪 Django 项目模型的状态。它还提供了一种方法来向组发送电子邮件,当状态更改时。