2012-10-22 66 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

相关问题