我可以在 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
对象可以更改其 Debit
或 Credit
值,而这不会 "fire" 信号,因此不会进行任何更新。即使您还为此类事件添加逻辑,仍然可能会发生信号不触发的情况,因为例如批量更新将超过信号系统。
通常最好不要存储数据聚合,因为这会导致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
但这可能仍然不够,因为您随后需要对日期等进行一些适当的过滤。
这是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
对象可以更改其 Debit
或 Credit
值,而这不会 "fire" 信号,因此不会进行任何更新。即使您还为此类事件添加逻辑,仍然可能会发生信号不触发的情况,因为例如批量更新将超过信号系统。
通常最好不要存储数据聚合,因为这会导致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
但这可能仍然不够,因为您随后需要对日期等进行一些适当的过滤。