Django - 默认字段值依赖于其他字段的值

13


我有一个问题,需要设置默认字段值。我想做什么?我希望类“Packages”中的价格成为类“Bill”中“priceNoTax”的默认值。正如您所看到的,这三个类是逻辑上相互连接的。
示例:账户1拥有ID为1的套餐。该套餐的价格为100美元。账户1的“priceNoTax”默认值为100美元。

如何做到?由于我是相对较新的人,因此需要帮助。

models.py

class Packages(models.Model):
     #other fields
     price = models.IntegerField(validators=[MinValueValidator(1)], verbose_name="Price of package")

class Account(models.Model):
     startDate = models.DateField(verbose_name="Start date")
     finishDate = models.DateField(verbose_name="Finish date")
     idPackage = models.ForeignKey(Packages, on_delete=models.CASCADE, verbose_name="Package")

class Bill(models.Model):
     date = models.DateField(default=datetime.now())
     tax = models.FloatField(default=0.20)
     priceNoTax = models.IntegerField()
     priceTax = models.FloatField(default=priceNoTax+(priceNoTax*tax))
     idAccount = models.ForeignKey(Account, on_delete=models.CASCADE, verbose_name="Account")

     def __str__(self):
         return self.date

非常感谢!!!


你是如何将信息传递到模型中的?你是使用管理页面还是从其他位置传递信息?我可以想到几种方法来实现这个目标,但没有一种能够将默认属性设置为另一个模型的值。 - Matthew Dumas
你不需要为我提供priceNoTaxpriceTax这两个字段,因为它们已经逻辑上相互关联了。如果你想要访问价格,你可以直接从Bill类中查询,例如:Bill.objects.filter(idAccount__idPackage__price)。这样可以减少重复变量的使用。 - Lord Salforis
3个回答

9
也许可以将这个功能加入你的账单类中?
def save(self, *args, **kwargs):
    if self.priceNoTax is None:
        self.priceNoTax = self.idAccount.idPackage.price
    super(Bill, self).save(*args, **kwargs)

2
这是为了存储而不是设置默认值。 - somenxavier

8
为什么需要将它作为字段?你认为有人会想要在不改变价格和税费的情况下更改总价吗?如果不一定需要作为字段,你可以将其作为方法。
class Bill(models.Model):
     date = models.DateField(default=datetime.now())
     tax = models.FloatField(default=0.20)
     priceNoTax = models.IntegerField()
     idAccount = models.ForeignKey(Account, on_delete=models.CASCADE, verbose_name="Account")

     def priceTax(self):
       return self.priceNoTax + (self.priceNoTax*self.tax)

     def __str__(self):
         return self.date

你仍然可以在模板中使用 {{ bill.priceTax }} 相同的方式。但在代码中,你需要使用 bill.priceTax()

这样,无论税率或不含税价格如何更改,带税价格都应该始终保持最新。

你也可以使用 @property 装饰器来避免在代码中将其作为函数调用。

@property
def priceTax(self):
   return self.priceNoTax + (self.priceNoTax*self.tax)

更多内容请参见https://docs.djangoproject.com/en/2.0/topics/db/models/#model-methods。该页面涉及到与数据库模型相关的方法。

2
十年后... 这种方法的一个问题是使用models.F()表达式无法访问 priceTax. - keepAlive
1
如果你担心这个问题,你可以将它添加到查询集中 https://dev59.com/lGMm5IYBdhLWcg3wVt4s#42491803。这仍然不需要进行数据库更改,因此不会有大规模的迁移和10年后的巨大问题。 - kichik
抱歉,“10年后”这个说法...我不知道我怎么了,但似乎我误读了日期...实际上,那时候没有什么东西超过2年...尽管时间飞逝,这可能比我们想象的更快成为现实..已经过去了大约6年....话虽如此,祝你新年快乐! - keepAlive

-2

@kichik回答了如何使用模板标签显示默认值,我建议通过JavaScript实现自动计算。

当然,你需要验证用户输入或者像@Chris Curvey所说的那样实现save()方法。


显示信息不是问题。https://docs.djangoproject.com/en/2.0/ref/models/fields/#default 这似乎是正确的答案。 - wm3ndez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接