1

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

Philip Mutua
  • 6,016
  • 12
  • 41
  • 84
  • For anyone who needs help with this you can go to this example repository I added comments in the code https://github.com/somacode1/example-implementation-django-friendly-finite-state-machine-support – Philip Mutua Feb 23 '23 at 15:10

0 Answers0