所以我有一个FK-d共享的交易模型。在“帐户”视图中,我具有这些交易的ModelFormset,并且可以通过遍历表单并将其保存来保存多个交易。
在我的交易记录的save()方法上,我尝试更新链接的Share上的余额。如果我保存一个事务,这将起作用,但是当我发布包含多个事务的ModelFormset时,每次我在Transaction save()覆盖中的 self.share.balance = self.share.balance + amt 行中(对于每个新交易),share.balance就是保存表单集中的任何先前交易之前的水平。
有人知道为什么以前保存的交易增加的股份余额额不会在以后的保存中进行吗(为什么只将最后一笔交易的数额添加到股份余额中)?
交易模型,该模型应更新父模型 Share
上的余额class Transaction(models.Model):
share = models.ForeignKey(Share, on_delete=models.CASCADE, null=True, blank=True)
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=True, blank=True)
db_cr = models.CharField(choices=DBCR, max_length=2)
amt = models.DecimalField('Amount', max_digits=11, decimal_places=2)
post_dt = models.DateTimeField('Post Time', null=True, blank=True)
def save(self, *args, **kwargs):
if not self.pk:
...
if self.share:
if self in self.share.transaction_set.all():
logging.error('Transaction %s already posted' % self.id)
return False
amt = self.amt if self.db_cr == 'cr' else -self.amt
self.share.balance = self.share.balance + amt
self.share.save()
共享模型
class Share(models.Model):
name = models.CharField(max_length=80)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
definition = models.ForeignKey(ShareDef, on_delete=models.PROTECT)
balance = models.DecimalField('Balance', max_digits=11, decimal_places=2, default=0)
def __str__(self):
return '%s %s %s %s'%(self.account,
self.name,
self.definition.sym_code,
self.balance )
def save(self, *args, **kwargs):
if not self.pk:
if not self.name:
self.name = self.definition.name
super(Share, self).save(*args, **kwargs)
在视图中,我有一个交易表单集
#...in view
TranFormSet = modelformset_factory(Transaction, exclude=('origin','ach_entry'), extra=1)
if request.method=='POST':
...
tran_formset = TranFormSet(request.POST)
...
if tran_formset.is_valid():
for form in tran_formset:
tran = form.save(commit=False)
tran.account = account
tran.origin = 'tt'
tran.save()
else:
#...following kind of weird because of how I'm setting querysets of ModelChoiceFields
kwargs = {'account_instance': account}
tran_formset = TranFormSet(queryset=Transaction.objects.none())
tran_formset.form = (curry(TranForm, **kwargs))
表格
class TranForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
account_instance = kwargs.pop('account_instance', None)
super(TranForm, self).__init__(*args, **kwargs)
if account_instance:
self.fields['share'].queryset = account_instance.share_set.all()
if self.instance.pk:
del self.fields['share']
class Meta:
model=Transaction
exclude=['origin', 'ach_entry', 'account']
post_dt = forms.DateTimeField(initial=datetime.date.today(), widget=forms.TextInput(attrs=
{
'class': 'datepicker'
}))
share = forms.ModelChoiceField(empty_label='---------', required=False, queryset=Share.objects.all())
答案 0 :(得分:1)
目前尚不清楚是什么原因引起的,但是在单个self.share.balance
查询中执行update()
的更新可能会有所帮助。可以使用F expressions:
from django.db.models import F
class Transaction(models.Model):
# ...
def update_share_balance(self):
if self.db_cr == "cr":
amount = self.amt
else:
amount = -self.amt
# By using the queryset update() method, we can perform the
# change in a single query, without using a potentially old
# value from `self.share.balance`
return Share.objects.filter(id=self.share_id).update(
balance=F("balance") + amount
)
def save(self, *args, **kwargs):
if not self.pk:
# ...
if self.share:
# ...
self.update_share_balance()
# Also, be sure to call the super().save() method at the end!
super().save(*args, **kwargs)