这里我有两个模型。在这些模型中,我想使Ledger模型中的amount_to_pay值动态化。例如,对于这两个模型,我有两种不同的形式,并且如果用户选择来自分类账模型并为amount_to_pay字段提供一些值,如果仅ledger.id和expense.payment_option_id相同,则应替换分类账模型中的amount_to_pay值。我该怎么做?
models.py
class Expense(models.Model):
pay_from = models.CharField(max_length=200)
payment_option = models.ForeignKey('Ledger', on_delete=models.CASCADE)
amount_to_pay = models.IntegerField(default=0)
expense_date = models.DateField(default=datetime.date.today)
expense_type = models.ForeignKey(ExpenseType, on_delete=models.CASCADE)
note = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = AutoSlugField(unique_with='id', populate_from='expense_type')
def get_amount_to_pay(self):
return self.amount_to_pay
class Ledger(models.Model):
name = models.CharField(max_length=200)
account_number = models.CharField(max_length=250, unique=True)
account_type = models.CharField(max_length=200)
opening_balance = models.IntegerField(default=0)
amount_to_pay = models.IntegerField(default=0, blank=True, null=True)
current_balance = models.IntegerField(default=0, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = AutoSlugField(unique_with='id', populate_from='name')
def save(self, *args, **kwargs):
self.amount_to_pay = Expense.get_amount_to_pay(self)
# here how can i save the amount_to_pay from expense form if the ledger.id and expense.payment_option.id matches??
#i got stuck here.
self.current_balance = self.opening_balance - self.amount_to_pay
super(Ledger, self).save(*args, **kwargs)
答案 0 :(得分:1)
我认为您应该在Ledger
模型中进行更改,而不是在Expense
模型中进行更改,像这样:
class Expense(models.Model):
...
def save(self, *args, **kwargs):
self.payment_option.amount_to_pay = self.payment_option.amount_to_pay + self.amount_to_pay
self.payment_option.save()
super(Expense, self).save(*args, **kwargs)
但是,老实说,解决方案对我来说并不好。原因是您将相同的数据保存在2个地方(费用和分类帐中)。相反,它应该是一次,然后应动态计算amount_to_pay
中的Ledger
值。像这样:
from django.db.models import Sum
class Ledger(...):
@property
def amount_to_pay(self):
# I am using a property method to show the amount_to_pay value.
# FYI: in this way, you need to remove amount_to_pay field from Ledger model
return self.opening_balance - self.expense_set.all().aggregate(a_sum=Sum('amount_to_pay')).get('a_sum', 0)
这样,对于每个分类帐,值amount_to_pay
将在运行时动态计算。例如:
for l in Ledger.objects.all():
l.amount_to_pay
如果您不愿使用先前解决方案中的每个l.amount_to_pay
(因为它是从DB动态计算出amount_to_pay)来命中数据库的,那么您始终可以annotate
来使用该值。像这样:
对于此解决方案,您需要更改Expense
模型并添加related_name
:
class Expense(models.Model):
pay_from = models.CharField(max_length=200)
payment_option = models.ForeignKey('Ledger', on_delete=models.CASCADE, related_name='expenses')
然后像这样在查询中使用related_name
(仅供参考:您无法在 Ledger 模型中保留 def amount_to_pay(...)
方法用于以下用途示例):
from django.db.models import Sum, F, ExpressionWrapper, IntegerField
ledgers = Ledger.objects.all().annotate(expense_sum=Sum('expenses__amount_to_pay')).annotate(amount_to_pay=ExpressionWrapper(F('opening_balance') - F('expense_sum'), output_field=IntegerField()))
# usage one
for l in ledgers:
l.amount_to_pay
# usage two
ledgers.values('amount_to_pay')
答案 1 :(得分:0)
最好的是,您可以使用前键来以任何方式覆盖save方法中的调用。
set Path="D:\hello\abc\old"
for /f "tokens=*" %%a in ('dir /A:-D /B /O:-D /S %Path%') do set NEW=%%a&& goto:n
:n
echo %NEW%
答案 2 :(得分:0)
检查Ledger是否有孩子,然后更新它:
class Expense(models.Model):
def save(self, *args, **kwargs):
self.payment_option.amount_to_pay = self.payment_option.amount_to_pay + self.amount_to_pay
self.payment_option.save()
super(Expense, self).save(*args, **kwargs)