2012-10-22 101 views
44

我對django有個疑問。Django post_save()信號的實現

我這裏有

class Product(models.Model): 
    name = models.CharField(max_length=255) 
    price = models.DecimalField(default=0.0, max_digits=9, decimal_places=2) 
    stock = models.IntegerField(default=0) 

    def __unicode__(self): 
     return self.name 

class Cart(models.Model): 
    customer = models.ForeignKey(Customer) 
    products = models.ManyToManyField(Product, through='TransactionDetail') 
    t_date = models.DateField(default=datetime.now()) 
    t_sum = models.FloatField(default=0.0) 

    def __unicode__(self): 
     return str(self.id) 

class TransactionDetail(models.Model): 
    product = models.ForeignKey(Product) 
    cart = models.ForeignKey(Cart) 
    amount = models.IntegerField(default=0) 

多對多模式對於創建1臺車對象,我可以插入多達新TransactionDetail對象(產品和數量)。我的問題是。我怎樣才能實現觸發器?我想要的是,無論何時創建交易細節,我都希望產品的庫存量減去交易訂單數量。

我讀過關於post_save(),但我不知道如何實現它。 也許這樣的事情

時:post_save(TransactionDetail, 車)#Cart對象,其中TransactionDetail.cart = Cart.id

Cart.stock -= TransactionDetail.amount 
+3

如果你這樣做,你很可能會遇到競爭條件。 –

回答

109

如果你真的想使用信號來實現這一點,在這裏我們簡要如何,

from django.db.models.signals import post_save 
from django.dispatch import receiver 

class TransactionDetail(models.Model): 
    # ... fields here 

# method for updating 
@receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count") 
def update_stock(sender, instance, **kwargs): 
    instance.product.stock -= instance.amount 
    instance.product.save() 
+19

這個例子是在django文檔中嚴格缺失的 –

+1

這對我來說工作正常,但不知道爲什麼它在未知長度的循環中 –

+3

我得到最大遞歸深度超過錯誤,因爲我將實例本身保存在'@ receiver'功能。我如何實現更新自我模型?我是否必須重寫'save()'模型的方法? – Dipak

10

個人而言,我會重寫TransactionDetail的save()方法,並在那裏保存新TransactionDetail然後運行

self.product.stock -= self.amount 
self.product.save() 
1

如果你想避免獲得maximum recursion depth exceeded,那麼你應該斷開信號,然後保存在信號處理程序中。上述(肯尼沉的回答)的例子,然後將:

from django.db.models.signals import post_save 
from django.dispatch import receiver 

class TransactionDetail(models.Model): 
    # ... fields here 

# method for updating 
@receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count") 
def update_stock(sender, instance, **kwargs): 
instance.product.stock -= instance.amount 

post_save.disconnect(update_stock, sender=TransactionDetail) 
instance.product.save() 
post_save.connect(update_stock, sender=TransactionDetail) 

這在Disconnect signals for models and reconnect in django詳盡的描述,用更抽象的和有用的例子。

另請參閱:django文檔中的https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals

相關問題