如何在Django rest fram中实现涉及用户审批的工作流系统

2024-03-28 22:16:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个休假模型类,它有以下定义。我想创建某种工作流程,在员工申请休假后输入所需字段。他/她将被重定向到pendingurl。显示申请休假的详细信息。然后主管批准或拒绝休假。关于如何在视图中使用class based视图实现这一点有什么想法吗?您还将在下面的视图中看到我是如何实现这一点的。在

class Leave(models.Model):

    """ Vacation timesheet model """
    LEAVE_STATUS_APPROVED = 1
    LEAVE_STATUS_REJECTED = 2
    LEAVE_STATUS_PENDING = 3

    LEAVE_STATUS_CHOICES = (
        (LEAVE_STATUS_APPROVED, 'approved'),
        (LEAVE_STATUS_REJECTED, 'rejected'),
        (LEAVE_STATUS_PENDING, 'pending'),
    )

    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 = models.CharField(max_length=80,
                                    choices=LEAVE_STATUS_CHOICES,
                                    default=LEAVE_STATUS_PENDING)
    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)

    class Meta:
        db_table = 'LeaveApplication'

    def __str__(self):
        return str(self.employee) + "__" + self.leave_type + "__" + self.id



class LeaveApplyAPI(APIView):

    """
        {   "applicant":1,
            "approver":1,
            "leave_type":1,
            "leave_subject":"Sick Off",
            "leave_reason":"Sick",
            "start_date":"YY-MM-DD",
            "return_date":"YY-MM-DD"
        }
    """

    lookup_field = 'pk'
    # permission_classes = (permissions.DjangoObjectPermissions,)
    serializer_class = ApplyLeaveSerializer

    def total_days(self, start_date, return_date):
        oneday = timedelta(days=1)
        # convert str to datetime
        start_date = datetime.strptime(start_date, '%Y-%m-%d')
        return_date = datetime.strptime(return_date, '%Y-%m-%d')
        total_days = 0
        while (start_date <= return_date):
            if not start_date.isoweekday() in (6, 7):
                total_days += 1
            start_date += oneday
        return total_days

    def get(self, request, format=None):
        leaves = Leave.objects.all()
        serializer = ApplyLeaveSerializer(leaves, many=True)
        return Response(serializer.data)

    def post(self, request, *args, **kwargs):
        print(request.data)

        start_date = request.data.get('start_date')
        return_date = request.data.get('return_date')
        total_days = self.total_days(start_date, return_date)

        applicant = Employee.objects.get(id=request.data.pop('applicant'))

        approver = Employee.objects.get(id=request.data.pop('approver'))

        leave_type = LeaveType.objects.get(id=request.data.pop('leave_type'))
        leave_subject = request.data.get('leave_subject')
        leave_reason = request.data.get('leave_reason')

        leave = Leave.objects.create(**request.data)
        leave.total_days = total_days
        leave.applicant = applicant
        leave.approver = approver
        leave.leave_type = leave_type
        leave.leave_subject = leave_subject
        leave.leave_reason = leave_reason
        leave.save()

        serializer = ApplyLeaveSerializer(leave)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

Tags: selftruedatagetdatereturnmodelsrequest
1条回答
网友
1楼 · 发布于 2024-03-28 22:16:43

将视图分隔为LeaveApplyViewLeaveApproveView,以及两个相应的序列化程序

您可以有两个序列化程序,LeaveApplySerializer和{},字段设置为只读。例如(因为我没有实际的序列化程序定义,所以我使用我自己的:

这是apply serializer的一个示例,其中要编辑的字段(如原因/类型)是可编辑的,而其他字段是只读的

class LeaveApplySerializer(serializers.ModelSerializer):
    class Meta:
        model = Leave
        fields = (
            'leave_id',
            'applied_on',
            .
            .
            .
            'total_days',
        )
        read_only_fields = (  # Make the fields that the applicant can't edit read-only
            'approver',
            'approved',
            'rejected',
            'comment',  # If this is an appoval field   
        )

这是approve序列化程序的一个示例,其中要编辑的字段(如approved/rejected)是可编辑的,而其他字段是只读的

^{pr2}$

最后,为批准和应用构建两个单独的视图;或者根据视图的用户/操作类型动态选择正确的serailizer。在

然后,您可以在LeaveApproveView上使用自定义的permission_class,仅允许审批者编辑此模型

class LeaveApproverPermission(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        """
        Return `True` if the user us an approver for the leave.
        """
        return request.user == obj.approver.user

一个建议:休假和审批似乎是相当不重叠的,您可能会从模型级别将它们分离而受益。为什么不提供两种型号:

class Leave和{}之间有OneToOneField的映射?在

相关问题 更多 >