2014-10-29 90 views
2

我是Django和Python的新手,我想做一些我经常在Java EE中执行的操作。Django - 基于其他字段的更新模型字段

考虑下面的模型(只有相关的类):

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 

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

我以前在Java POJO中做的事情是将这个逻辑包含在setter方法中。我试过使用python属性来封装item属性,但是Django直接在引擎盖下更新字段,所以这会破坏一些自动功能。我也尝试了继承ForeignKey接受回调函数,但我找不到方法来调用容器类的方法。

我想这样做,所以我可以提供用户界面默认的,但我不想在视图中包括逻辑这个逻辑,因为在概念上我觉得这个逻辑应该在模型上(服务器端)

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

谢谢!

回答

0

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

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 

然后使用它像这样:

print(sd.unit_price) 
sd.unit_price = 500 
sd.save() 
+0

现在我有了更多的经验,我可以看到我在django生态系统中做的没有意义,但是因为这正确回答了我的问题,所以我接受了答案。谢谢! – 2015-08-21 09:31:59

1

看看这是否适合你。我们重写保存方法并检查是否存在pk。如果pk是无,我们知道SaleDetail是新的。然后,我们看看是否有unit_price。如果没有unit_price,我们将其设置为Item.default_price

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 save(self, *args, **kwargs): 
     # Make sure this is the first save (pk should be None) and there is no unit_price set 
     if self.pk is None and not self.unit_price: 
      self.unit_price = self.item.default_price 
     elif not self.unit_price: 
      self.unit_price = self.item.default_price 

     # Call the original save method 
     super(SaleDetail, self).save(*args, **kwargs) 
+0

嗨@迈克尔,寻找答案感谢。但是,正如我在问题中所述,我需要在用户尝试保存该对象之前执行此操作。 – 2014-10-30 12:48:19

+0

我个人唯一能想到的其他事情就是在模块上添加一个方法来获取'unit_price'。它将使用与超级存储方法相同的逻辑,除了它会在需要的实例中返回'item.default_price'。我不完全确定你是如何收集这些信息的(表格?),因此很难帮助你解决问题。如果“SaleDetail”实际上是收据的“订单项”,则应将该方法放在'SaleDetail'模型上。 – 2014-10-30 15:02:02

+0

很好的覆盖'save'方法 – ChrisFreeman 2018-01-13 07:53:45

相关问题