我可以在Django pre_save signals中执行查询吗?

2024-04-26 11:11:06 发布

您现在位置:Python中文网/ 问答频道 /正文

这是模型.py在

class ledger1(models.Model):
    User = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True)
    Company = models.ForeignKey(company,on_delete=models.CASCADE,null=True,blank=True,related_name='Companys')
    Creation_Date = models.DateField(default=datetime.now)
    name = models.CharField(max_length=32,unique=True)
    Opening_Balance = models.DecimalField(max_digits=19,decimal_places=2)
    Closing_balance = models.DecimalField(max_digits=10,decimal_places=2)


class journal(models.Model):
    User = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=True,blank=True)
    Company = models.ForeignKey(company,on_delete=models.CASCADE,null=True,blank=True,related_name='Companyname')
    Date = models.DateField()
    By = models.ForeignKey(ledger1,on_delete=models.CASCADE,related_name='Debitledgers')
    To = models.ForeignKey(ledger1,on_delete=models.CASCADE,related_name='Creditledgers')
    Debit = models.DecimalField(max_digits=10,decimal_places=2,)
    Credit = models.DecimalField(max_digits=10,decimal_places=2)

我想用django查询生成一个数学公式,公式的结果将显示在ledger1.Closing_Balance字段中

所以我试过了:

^{pr2}$

在django有可能吗??? 因为如果我运行这个,我会得到不支持的操作数错误。。。在

有没有其他的代码???在

如果有人知道…请帮忙

提前谢谢你


Tags: nametrueonmodelsdeletenullmaxcascade
1条回答
网友
1楼 · 发布于 2024-04-26 11:11:06

不支持的操作数异常与查询本身无关,但与您编写的表达式有关:

Closing_balance = (
   ledger1.objects.annotate(debitsum=Sum('Debitledgers__Debit')) +
   instance.Opening_Balance -
   ledger1.objects.annotate(creditsum=Sum('Creditledgers__Credit'))
)

所以这里您要将QuerySets与实际值一起添加,这没有任何意义。您可能希望使用一个.aggregate(..),然后将它包含的值包装起来,例如:

^{pr2}$

但也就是说,使用信号来预先计算聚集通常是一个好主意。因为例如一个journal对象可以改变它的DebitCredit值,而这不会“触发”信号,因此不会进行任何更新。即使您也为这些事件添加了逻辑,仍然可能发生信号不触发的情况,因为例如批量更新将超过信令系统。在

通常,存储数据聚合最好是而不是,因为这会导致data duplication,正如文章所说“会滋生冗余和不一致。。如果您想计算这样的聚合,最好在数据库级别使用(物化)视图。在

编辑:但是查询本身似乎没有任何意义。如果更新ledger记录,则可以执行筛选,并按此方式计算更新:

@receiver(pre_save, sender=ledger1)
def update_user_closing_balance(sender,instance,*args,**kwargs):
    debit = instance.Debitledgers.aggregate(debit=Sum('Debit'))['debit']
    credit = instance.Creditledgers.aggregate(credit=Sum('Credit'))['credit']
    instance.Closing_balance = instance.Opening_Balance + debit - credit

但这可能仍然不够,因为您需要对日期进行适当的筛选,等等

相关问题 更多 >