Django - 基于另一个字段更新模型字段

Aní*_*ero 6 python django orm field model

我是 Django 和 Python 的新手,我想做一些我曾经在 Java EE 中经常做的事情。

考虑以下模型(仅相关类):

class Item(models.Model):
    name = models.CharField(max_length=40)
    default_price = models.DecimalField(max_digits=6, decimal_places=2, default=50)

    def __unicode__(self):
        return self.name


class SaleDetail(models.Model):
    item = models.ForeignKey(Item)
    deposit = models.ForeignKey(Deposit)
    quantity = models.PositiveIntegerField()
    unit_price = models.DecimalField(max_digits=6, decimal_places=2)
    sale = models.ForeignKey(Sale)

    def item_updated(self, value):
        if self.unit_price == None:
            self.unit_price = value
Run Code Online (Sandbox Code Playgroud)

我想要做的是,每一个时间Item被添加到SaleDetail,更新SaleDetail.unit_priceItem.default_price是否SaleDetail是新的或没有unit_price设置。

我过去在 Java POJO 中所做的是将这个逻辑包含在 setter 方法中。我尝试使用 python 属性来封装item属性,但 Django 直接在引擎盖下更新该字段,因此这会破坏一些自动功能。

我还尝试将 ForeignKey 子类化以接受回调函数,但我找不到在容器类上调用方法的方法。

我想这样做,所以我可以为 UI 提供一个默认值,但我不想在视图逻辑中包含这个逻辑,因为从概念上讲,我认为这个逻辑应该在模型上(服务器端)

这种情况下的其他用途是更新每个销售明细和销售的总计。我想在用户决定保存销售之前计算这个,所以保存信号不起作用。

谢谢!

小智 4

“单价”实际上是两个不同字段的函数。因此我倾向于这样写:

class Item(models.Model):
    name = models.CharField(max_length=40)
    default_price = models.DecimalField(max_digits=6, decimal_places=2, default=50)

    def __unicode__(self):
        return self.name

class SaleDetail(models.Model):
    item = models.ForeignKey(Item)
    deposit = models.ForeignKey(Deposit)
    quantity = models.PositiveIntegerField()
    entered_unit_price = models.DecimalField(max_digits=6, decimal_places=2, default=None)
    sale = models.ForeignKey(Sale)

    @property
    def unit_price(self, value):
        if self.entered_unit_price is None:
            return self.item.default_price
        else:
            return self.entered_unit_price

    @unit_price.setter
    def unit_price(self, value):
        self.entered_unit_price = value
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

print(sd.unit_price)
sd.unit_price = 500 
sd.save()
Run Code Online (Sandbox Code Playgroud)