我在模型中有一个字段,它将根据两个值计算。问题现在我的所有代码都是使用手动SUM
或AVG
我想要做的是设计模型的另一种方法,同时保持相同的逻辑。我想要这样做的主要原因,因为我需要利用djagno聚合和注释函数。另外,要在数据库端计算这些值,而不是在Python中。
class Employee(models.Model):
name = models.CharField(....)
..
salary = models.FloatField(....)
class Benefit(models.Model):
employee = models.ForeignKey('Employee')
# this field can be
# Percentage (ex %2 from employee main salary)
# Fixed Price (ex $150)
# days
calculation_type = thetopchoices(FIX,PER,DAYS)
# this field should be the value
# of the percentage or the fixed amount
custom = models.PositiveIntegerField(....)
所以基本上,我有检查计算类型的方法,并根据它获得了收益的数额。
def calculate(self):
if self.calculation_type == 'PER':
return self.employee.salary * self.custom
elif self.calculation_type == 'FIX':
return self.custom
else
return ( self.employee.salary / 30 ) * self.custom
@property
def amount(self):
return self.calculate()
现在问题是如何计算每个员工的福利总额。最好的解决方案是使用Django聚合在数据库中进行计算。但是,使用这种设计永远不会有效,因为Django需要数量才能成为一个真实的领域。
到目前为止我的解决方案,但我认为它没有效率。
def get_total_amount_of_benefits(self):
total = 0
for b in employee.benefit_set.all():
total += b.amount
return total
答案 0 :(得分:1)
我认为您应重新定义Benefit
模型,添加amount
字段,该字段将根据模型calculation_type
中的custom
和save
字段值自动计算:
class Benefit(models.Model):
employee = models.ForeignKey('Employee')
# this field can be
# Percentage (ex %2 from employee main salary)
# Fixed Price (ex $150)
# days
calculation_type = thetopchoices(FIX,PER,DAYS)
# this field should be the value
# of the percentage or the fixed amount
custom = models.PositiveIntegerField(....)
amount = models.PositiveIntegerField(...., editable=False) # auto calculated field in save
def __init__(self, *args, **kwargs):
super(Benefit, self).__init__(*args, **kwargs)
self.__original_calc_type = self.calculation_type
self.__original_custom = self.custom
def calculate(self):
employee = self.employee
if self.calculation_type == 'PER':
amount = employee.salary * self.custom
elif self.calculation_type == 'FIX':
amount = self.custom
else
amount = ( employee.salary / 30 ) * self.custom
return amount
def save(self, *args, **kwargs):
recalculate = kwargs.pop('recalculate', False)
if self.__original_calc_type != self.calculation_type or self.__original_custom != self.custom or recalculate:
self.amount = self.calculate()
super(Benefit, self).save(*args, **kwargs)
self.__original_calc_type = self.calculation_type
self.__original_custom = self.custom
现在可以轻松获得所有福利金额:
from django.db.models import Sum
class Employee(models.Model):
...
...
@property
def benefits_amount(self):
d = self.benefit_set.aggregate(total_amount=Sum('amount'))
return d['total_amount'] if d['total_amount'] else 0
如果您希望稍后根据您拥有的任何条件更新优惠,则需要按照以下方式执行此操作:
for benefit in employee.benefit_set.all():
benefit.save(recalculate=True)