Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在django rest框架中实现涉及用户批准的工作流系统_Python_Python 3.x_Django Rest Framework_Django Views - Fatal编程技术网

Python 如何在django rest框架中实现涉及用户批准的工作流系统

Python 如何在django rest框架中实现涉及用户批准的工作流系统,python,python-3.x,django-rest-framework,django-views,Python,Python 3.x,Django Rest Framework,Django Views,我有一个休假模型类,它有以下定义。我想创建一种工作流程,员工在输入必填字段后申请休假。他/她将被重定向到挂起的url。这将显示申请休假的详细信息。然后,主管将批准或拒绝休假。如何使用基于类的视图在视图中实现这一点?您还将在下面的视图中看到我是如何实现这一点的 class Leave(models.Model): """ Vacation timesheet model """ LEAVE_STATUS_APPROVED = 1 LEAVE_STATUS_REJECTED

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

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)

将视图分为一个LeaveApplyView和一个LeaveApproveView以及两个相应的序列化程序

您可以有两个序列化程序;LeaveApplySerializer和LeaveApproveSerializer,字段设置为只读(如适用)。例如,由于我没有实际的序列化程序定义,因此我使用自己的:

这是应用序列化程序的一个示例,其中要编辑的字段(如原因/类型)是可编辑的,而其他字段是只读的

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   
        )
class LeaveApproveSerializer(serializers.ModelSerializer):
        class Meta:
            model = Leave
            fields = (
                .
                .
                .
            )
            read_only_fields = (  # Make the fields that the appover can't edit read-only
                'applicant',
                'leave_type'
                .
                .
                .
            )
这是approve序列化程序的一个示例,其中要编辑的字段(如approved/rejected)是可编辑的,而其他字段是只读的

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   
        )
class LeaveApproveSerializer(serializers.ModelSerializer):
        class Meta:
            model = Leave
            fields = (
                .
                .
                .
            )
            read_only_fields = (  # Make the fields that the appover can't edit read-only
                'applicant',
                'leave_type'
                .
                .
                .
            )
最后,为批准和申请充实两个独立的视图;或者根据视图的用户/操作类型动态选择正确的serailizer

然后,您可以在LeaveApproveView上使用自定义权限类,仅允许审批人编辑此模型

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
一个建议是:休假和批准似乎是相当不重叠的,在模型级别将它们分开可能会让您受益。为什么没有两种型号:


班级休假和班级休假批准之间有一个OneToOneField映射?

我认为你的建议是一个好主意。