簡體   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