I am making a leave process where an applicant will apply for leave and the leave will be queued so that the approver will either approve or reject the leave application. I came across django-fsm and drf-fsm-transitions and I thought of implementing this kind of work flow. I am using django 1.11
+ python3
+ django_rest_framework
to build my API.
In the django app I have imported from django_fsm import transition, FSMIntegerField
to models.py
.
Leave Class
class Leave(models.Model):
LEAVE_STATUS_CREATED = 0
LEAVE_STATUS_APPLIED = 1
LEAVE_STATUS_APPROVED = 2
LEAVE_STATUS_REJECTED = 3
LEAVE_STATUS_PENDING = 4
LEAVE_STATUS_COMPLETE = 5
LEAVE_STATUS_CHOICES = (
(LEAVE_STATUS_CREATED, 'created'),
(LEAVE_STATUS_APPLIED, 'applied'),
(LEAVE_STATUS_APPROVED, 'approved'),
(LEAVE_STATUS_REJECTED, 'rejected'),
(LEAVE_STATUS_PENDING, 'pending'),
(LEAVE_STATUS_COMPLETE, 'complete'),
)
leave_id = models.AutoField(primary_key=True)
applicant = models.ForeignKey(
Employee, related_name='applicant', on_delete=models.CASCADE, null=True)
approver = models.ForeignKey(
Employee, related_name='approver', on_delete=models.CASCADE, null=True)
applied_on = models.DateTimeField(auto_now_add=True)
responded_on = models.DateTimeField(auto_now=True, null=True)
leave_type = models.ForeignKey(LeaveType, null=True)
approved = models.BooleanField(default=False)
rejected = models.BooleanField(default=False)
start_date = models.DateField()
return_date = models.DateField()
leave_status = FSMIntegerField(
choices=LEAVE_STATUS_CHOICES, default=LEAVE_STATUS_CREATED, protected=True)
comment = models.TextField(max_length=200)
leave_subject = models.CharField(max_length=40)
leave_reason = models.TextField(max_length=200)
total_days = models.IntegerField(null=True)
Transition
I have then implemented the following transitions in the leave class:
@transition(field=leave_status, source=LEAVE_STATUS_CREATED, target=LEAVE_STATUS_APPLIED)
def apply(self, comment):
self.applicant = applicant
self.leave_type = leave_type
self.start_date = start_date
self.return_date = return_date
self.leave_subject = leave_subject
self.leave_reason = leave_reason
print("Apply %s Leave").format(self.comment)
@transition(field=leave_status, source=LEAVE_STATUS_APPLIED, target=LEAVE_STATUS_APPROVED)
def approve(self, approver, responded_on, comment):
self.approver = approver
self.responded_on = responded_on
self.comment = comment
print("approve the leave")
@transition(field=leave_status, source=[LEAVE_STATUS_CREATED, LEAVE_STATUS_APPLIED], target=LEAVE_STATUS_REJECTED)
def reject(self, approver, responded_on, comment):
self.approver = approver
self.responded_on = responded_on
self.comment = comment
print("rejected leave ")
Then in the views I imported from drf_fsm_transitions.viewset_mixins import get_viewset_transition_action_mixin
Which I am getting the following logs when I run the server:
transitions = instance.get_all_status_transitions()
AttributeError: 'Leave' object has no attribute 'get_all_status_transitions'
Here is how my view class looks like:
class LeaveViewSet(
get_viewset_transition_action_mixin(Leave),
viewsets.ModelViewSet):
queryset = Leave.objects.all()
How to implement a class based view when using django-fsm in django