我希望租金下的金额在“帐户”下的金额上增加。当用户在租金中输入金额时,它应该扣除或添加账户中的金额,如果已付款则应重置或在未付款时保持不变。
class Account(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=250)
number = models.PositiveIntegerField(help_text="Account number", unique=True, blank=True, null=False)
currency = models.CharField(max_length=3, choices=ALLOWED_CURRENCIES)
creation_date = models.DateTimeField(auto_now_add=True)
amount = models.DecimalField(max_digits=MONEY_MAX_DIGITS, decimal_places=MONEY_DECIMAL_PLACES, help_text="Latest" "balance", default=0, blank=False, null=True)
class Rent(models.Model):
source = models.ForeignKey(Account, on_delete=models.CASCADE, verbose_name="Account holder.")
amount = models.DecimalField(max_digits=MONEY_MAX_DIGITS, decimal_places=MONEY_DECIMAL_PLACES)
date = models.DateTimeField(auto_now_add=True)
答案 0 :(得分:1)
您可以使用以下三种策略之一:
动态计算帐户的金额。您可以使用这样的方法(或者可能是缓存属性),而不是使用amount
字段:
from django.db.models import Sum
class Account(models.Model):
# ...
def amount(self):
result = self.rent_set.all().aggregate(
total_amount=Sum('amount'))
return result['total_amount']
这种方法的优势在于它始终准确:无论您如何创建和操作Account和Rent记录,此方法都将始终返回正确的数量。
它的缺点是每次调用它时都会发出查询。这会对性能产生影响。
保存或删除租金时更新帐户金额字段:
from django.db.models import Sum
class Account(models.Model):
# ...
def update_amount(self):
result = self.rent_set.all().aggregate(
total_amount=Sum('amount'))
self.amount = result['total_amount']
class Rent(models.Model):
# ...
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.account.update_amount()
self.account.save()
def delete(self, *args, **kwargs):
account = self.account
super().delete(*args, **kwargs)
account.update_amount()
account.save()
此方法的优点是金额存储在帐户记录中,因此无需在每次需要时重新计算,只有在保存Rent对象时才会重新计算。
缺点是你必须在Rent对象上调用save()
和delete()
。例如,您不能使用Rent.objects.all().delete(...)
或Rent.objects.all().update(...)
等查询集方法,因为您的自定义save()
和delete()
将不会被调用。
另一个问题是,如果您在数据库级别编辑/删除租借记录而不通过自定义代码,则不会更新金额。
收到post_save
/post_delete
signals后更新帐户金额(感谢user3375448提供建议):
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
@receiver(post_save, sender=Rent)
@receiver(post_delete, sender=Rent)
def my_handler(sender, instance, **kwargs):
instance.account.update_amount()
这基本上与之前的解决方案类似,它具有基本相同的优点和缺点。
以前的解决方案的一个改进是,在删除查询集时也会发送post_delete
。