我在模型中有一个字段,该字段将基于两个值进行计算。现在的问题是我所有的代码都是使用手动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
我认为您应该重新定义Benefit
模型,添加amount
将根据model中的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)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句