2014-10-29 171 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

相關問題