如何从另一个模型中操作一个模型字段的值?

时间:2022-06-04 07:10:31

I have two models

我有两个模型

class Employee(models.Model):
    name = models.CharField(max_length=20)
    ID = models.IntegerField()
    basic_salary = models.IntegerField()     
    total_leave = models.IntegerField(default = 14)
    paid_leave = models.IntegerField(default = 0)
    unpaid_leave = models.IntegerField(default = 0)

def __str__(self):
    return self.name

class Leave_management(models.Model):

    name = models.OnetoOneField(Employee,on_delete= models.CASCADE)
    reason = models.CharField(max_length=50)
    from = models.DateTimeField()
    to = models.DateTimeField()
    total_days = models.IntegerField()

     def __str__(self):
        return self.name

So,i want to minus 'total_days' of 'model-Leave_management' from 'total_leave' field of 'model-Employee'. And as per leaves taken i want to update 'paid_leave' and 'unpaid_leave' sections.

因此,我想从“模型-雇员”的“total_leave”字段中减去“模型- leave_management”的“total_days”。我想更新“paid_leave”和“unpaid_leave”部分。

I can perform so if these two models would be one model(example below), But i dont know how to perform so in different models.

如果这两个模型是一个模型(下面的例子),我可以执行,但是我不知道如何在不同的模型中执行。

def save(self,*args,**kwargs):
    if self.total_days<=self.total_leave:
        self.total_leave -= self.total_days
        self.unpaid_leave = 14 - self.total_leave
   else:
       self.total_days -= 14
       self.paid_leaves = self.total_days
   super(Model_name,self).save(*args,**kwargs)

` Please be guiding me.

“请给我带路。”

1 个解决方案

#1


1  

In fact your OneToOneField(..) to an Employee is not a name. At the database level it will store values that correspond to primary keys of an Employee, and in Django, name will be a lazy fetch to the corresponding Employee. Therefore I suggest to rename your function to (for example) employee.

事实上,你对员工的称呼并不是一个名字。在数据库级别,它将存储与雇员的主键对应的值,在Django中,名称将是对相应雇员的延迟获取。因此,我建议将您的函数重命名为(例如)employee。

Another problem is that you define it as a OneToOneField. That means that an Employee has one Leave_management. But based on the fields (reason, from, to, etc.), it looks like an Employee can have zero, one, or more Leave_managements. So that means it is a ForeignKey.

另一个问题是你把它定义为一个单场。这意味着一个雇员有一个离职管理。但是基于字段(原因、从、到等等),看起来员工可以有零个、一个或多个leave_management。这意味着它是一个外国人。

So our model looks like:

我们的模型是这样的:

class Leave_management(models.Model):

    employee = models.ForeignKey(Employee,on_delete= models.CASCADE)
    reason = models.CharField(max_length=50)
    from = models.DateTimeField()
    to = models.DateTimeField()
    total_days = models.IntegerField()

     def __str__(self):
        return self.employee.name

Like the __str__ function already suggests, we can obtain the name of the employee by querying self.employee, and we can then fetch its .name attribute.

就像__str__函数已经建议的那样,我们可以通过查询self获得雇员的名字。然后,我们可以获取它的.name属性。

But now the challenge is what to do when save a Leave_management object. In that case the number of total_leave and paid_leave should be updated.

但是现在的挑战是当保存一个Leave_management对象时该做什么。在这种情况下,应该更新total_leave和paid_leave的数量。

We first have to figure out the total number of total_days that are stored in Leave_management objects related to an Employee, this is equal to:

我们首先要算出存储在与员工相关的Leave_management对象中的total_days的总数,它等于:

(Leave_management.objects.filter(employee=some_employee)
                         .aggregate(totals=Sum('total_days'))['totals'] or 0

So we can then subtract this from 14, and store the (possibly) remaining days in paid_leave, like:

我们可以从14中减去这个,然后将(可能的)剩余的天数存储在paid_leave中,比如:

class Leave_management(models.Model):

    # ...

    def save(self, *args, **kwargs):
        super(Leave_management, self).save(*args, **kwargs)
        totals = (Leave_management.objects
                                  .filter(employee=some_employee)
                                  .aggregate(totals=Sum('total_days'))['totals'] or 0
        employee = self.employee
        unpaid = min(14, totals)
        employee.total_leave = 14 - unpaid
        employee.unpaid_leave = unpaid
        employee.paid_leave = totals - unpaid
        employee.save()

Note: typically we do not handle this by overriding the .save(..) function, but by using Django signals: triggers that can be implemented when certain objects are saved, etc. This especially should be used since the objects can be changed circumventing the .save(..) function, and sometimes such objects might get deleted as well. So the above is not a good design decision.

注意:通常我们不处理这种通过重写.save(. .)函数,但通过使用Django的信号:触发时,可以实现某些对象是保存,等等。这尤其应该使用因为对象可以改变绕过.save(. .)函数,有时这样的对象可能会被删除。所以上面的设计并不是一个好的决定。

Even when we use signals, it is a good idea to frequently (for example once a day) recalculate the total leave, and update the corresponding Employee models.

即使当我们使用信号时,最好经常(例如每天一次)重新计算总休假,并更新相应的员工模型。

#1


1  

In fact your OneToOneField(..) to an Employee is not a name. At the database level it will store values that correspond to primary keys of an Employee, and in Django, name will be a lazy fetch to the corresponding Employee. Therefore I suggest to rename your function to (for example) employee.

事实上,你对员工的称呼并不是一个名字。在数据库级别,它将存储与雇员的主键对应的值,在Django中,名称将是对相应雇员的延迟获取。因此,我建议将您的函数重命名为(例如)employee。

Another problem is that you define it as a OneToOneField. That means that an Employee has one Leave_management. But based on the fields (reason, from, to, etc.), it looks like an Employee can have zero, one, or more Leave_managements. So that means it is a ForeignKey.

另一个问题是你把它定义为一个单场。这意味着一个雇员有一个离职管理。但是基于字段(原因、从、到等等),看起来员工可以有零个、一个或多个leave_management。这意味着它是一个外国人。

So our model looks like:

我们的模型是这样的:

class Leave_management(models.Model):

    employee = models.ForeignKey(Employee,on_delete= models.CASCADE)
    reason = models.CharField(max_length=50)
    from = models.DateTimeField()
    to = models.DateTimeField()
    total_days = models.IntegerField()

     def __str__(self):
        return self.employee.name

Like the __str__ function already suggests, we can obtain the name of the employee by querying self.employee, and we can then fetch its .name attribute.

就像__str__函数已经建议的那样,我们可以通过查询self获得雇员的名字。然后,我们可以获取它的.name属性。

But now the challenge is what to do when save a Leave_management object. In that case the number of total_leave and paid_leave should be updated.

但是现在的挑战是当保存一个Leave_management对象时该做什么。在这种情况下,应该更新total_leave和paid_leave的数量。

We first have to figure out the total number of total_days that are stored in Leave_management objects related to an Employee, this is equal to:

我们首先要算出存储在与员工相关的Leave_management对象中的total_days的总数,它等于:

(Leave_management.objects.filter(employee=some_employee)
                         .aggregate(totals=Sum('total_days'))['totals'] or 0

So we can then subtract this from 14, and store the (possibly) remaining days in paid_leave, like:

我们可以从14中减去这个,然后将(可能的)剩余的天数存储在paid_leave中,比如:

class Leave_management(models.Model):

    # ...

    def save(self, *args, **kwargs):
        super(Leave_management, self).save(*args, **kwargs)
        totals = (Leave_management.objects
                                  .filter(employee=some_employee)
                                  .aggregate(totals=Sum('total_days'))['totals'] or 0
        employee = self.employee
        unpaid = min(14, totals)
        employee.total_leave = 14 - unpaid
        employee.unpaid_leave = unpaid
        employee.paid_leave = totals - unpaid
        employee.save()

Note: typically we do not handle this by overriding the .save(..) function, but by using Django signals: triggers that can be implemented when certain objects are saved, etc. This especially should be used since the objects can be changed circumventing the .save(..) function, and sometimes such objects might get deleted as well. So the above is not a good design decision.

注意:通常我们不处理这种通过重写.save(. .)函数,但通过使用Django的信号:触发时,可以实现某些对象是保存,等等。这尤其应该使用因为对象可以改变绕过.save(. .)函数,有时这样的对象可能会被删除。所以上面的设计并不是一个好的决定。

Even when we use signals, it is a good idea to frequently (for example once a day) recalculate the total leave, and update the corresponding Employee models.

即使当我们使用信号时,最好经常(例如每天一次)重新计算总休假,并更新相应的员工模型。