繁体   English   中英

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

[英]Can I perform queries in django pre_save signals?

这是models.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字段中

所以我尝试了这个:

@receiver(pre_save, sender=ledger1)
def update_user_closing_balance(sender,instance,*args,**kwargs):
    Closing_balance = ledger1.objects.annotate(debitsum=Sum('Debitledgers__Debit')) + instance.Opening_Balance - ledger1.objects.annotate(creditsum=Sum('Creditledgers__Credit'))
    instance.Closing_balance = Closing_balance

在Django有可能吗??? 因为如果我运行此命令,将会收到不受支持的操作数错误...

是否有其他替代代码???

如果有人知道...请帮助

先感谢您

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

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

所以在这里您将QuerySet与实际值一起添加,这没有任何意义。 您可能想使用的是.aggregate(..) ,然后将其中包含的值包装起来,例如:

debitsum = ledger1.objects.aggregate(debitsum=Sum('Debitledgers__Debit'))['debitsum']
creditsum = ledger1.objects.aggregate(creditsum=Sum('Creditledgers__Credit'))['creditsum']

Closing_balance = debitsum + instance.Opening_Balance - creditsum

话虽这么说,使用信号预先计算聚合通常不是一个好主意。 例如,由于journal对象可以更改其DebitCredit值,并且这不会“触发”信号,因此不会进行任何更新。 即使您还为此类事件添加逻辑,信号仍然可能发生,因为例如批量更新将超过信号系统。

通常最好不要存储数据聚合,因为这会导致数据重复 ,就像文章所说的那样“ 滋生了冗余和不一致 ”。 如果要计算此类聚合,最好在数据库级别使用(实例化)视图。

编辑 :但是查询本身似乎没有任何意义。 如果更新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

但这可能仍不足够,因为您随后需要对日期进行一些适当的过滤,等等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM