根据其他列更新 Django 模型列

update django models column based on other column

我有一个像这样的模型

class tbl_payment(models.Model):
    document_id                     = models.ForeignKey(tbl_invoice, on_delete=models.CASCADE)
    client_id                       = models.ForeignKey(tbl_customer, on_delete=models.CASCADE)
    total_amount                    = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    paid_amount                     = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    balance                         = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    date                            = models.DateField(blank=True, null=True)
    status                          = models.CharField(max_length=50)

现在我想做的是每当添加新记录或更改现有记录时,balance 应该更新为 total_amountpaid_amount 之间的区别(简单数学),并根据我的 balance 专栏,我想将 status 保存为 PaidPartial未付.

我想避免在我的视图中计算 balance 然后保存在数据库中,相反,我想将这部分移交给我的模型,以便我的模型处理 balance 而且我可以避免我潜意识里害怕的错误。

我开始知道这是这样做的

class tbl_payment(models.Model):
    document_id                     = models.ForeignKey(tbl_invoice, on_delete=models.CASCADE)
    client_id                       = models.ForeignKey(tbl_customer, on_delete=models.CASCADE)
    total_amount                    = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    paid_amount                     = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    balance                         = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
    date                            = models.DateField(blank=True, null=True)
    status                          = models.CharField(max_length=50)

    @property
    def balance(self, value):
        return self.total_amount - paid_amount
        

但是我应该传递什么来代替 value? 当我尝试获得这样的 due_amount 值时也是如此

tbl_bulk_payment.objects.get(pk=1).due_amount

它给出 due_amount() missing 1 required positional argument: 'value'

这样做的正确方法是什么?

你必须覆盖 save() 函数

    class tbl_payment(models.Model):
        class Status(models.TextChoices):
            paid = 'Paid', 'Paid'
            partial = 'Partial', 'Partial'
            unpaid = 'Unpaid', 'Unpaid'
            
        document_id                     = models.ForeignKey(tbl_invoice, on_delete=models.CASCADE)
        client_id                       = models.ForeignKey(tbl_customer, on_delete=models.CASCADE)
        total_amount                    = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
        paid_amount                     = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
        balance                         = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
        date                            = models.DateField(blank=True, null=True)
        status                          = models.CharField(max_length=50, choices=Status.choices)
    
        def save(self, *args, **kwargs):
            self.balance = self.total_amount - self.paid_amount
            
            if self.balance >= 0:
                self.status = Status.paid
            elif self.paid_amount == 0:
                self.status = Status.unpaid
            else:
                self.status = Status.partial
    
            super(tbl_payment, self).save(*args, **kwargs)

P.S。您的模型 class 名称不遵循 python 或 Django 命名规则。 class Payment(models.Model)会更好。

document_id => document。因为

payment = Payment.objects.get(pk=1)
payment.document_id

在这种情况下 payment.document_id 将 return document 实例。 (不是文档实例的 ID)。所以 documentdocument_id

更像 Django 风格