Django post_save()信号实现

时间:2012-10-22 15:14:12

标签: python django django-models django-signals

我对django有疑问。

我在这里有ManyToMany模型

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()但我不确定如何实现它。 也许是这样的

when:post_save(TransactionDetail,            购物车)#Cart对象,其中TransactionDetail.cart = Cart.id

Cart.stock -= TransactionDetail.amount

5 个答案:

答案 0 :(得分:137)

如果你真的想用信号来达到这个目的,这里简要介绍一下,

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()

答案 1 :(得分:14)

我个人会覆盖TransactionDetail的save()方法并在那里保存新的TransactionDetail然后运行

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

答案 2 :(得分:5)

如果您想避免获取maximum recursion depth exceeded,那么在保存在信号处理程序中之前,您应该断开信号。上面的例子(Kenny Shen的回答)将是:

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

答案 3 :(得分:1)

事实上,解释Signals的文档在django.dispatch.Signal.connect中:

def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
    Connect receiver to sender for signal.

    Arguments:

        receiver
            A function or an instance method which is to receive signals.
            Receivers must be hashable objects.

            If weak is True, then receiver must be weak referenceable.

            Receivers must be able to accept keyword arguments.

            If a receiver is connected with a dispatch_uid argument, it
            will not be added if another receiver was already connected
            with that dispatch_uid.

        sender
            The sender to which the receiver should respond. Must either be
            a Python object, or None to receive events from any sender.

        weak
            Whether to use weak references to the receiver. By default, the
            module will attempt to use weak references to the receiver
            objects. If this parameter is false, then strong references will
            be used.

        dispatch_uid
            An identifier used to uniquely identify a particular instance of
            a receiver. This will usually be a string, though it may be
            anything hashable.

答案 4 :(得分:0)

如果您真的想在django中使用信号,请尝试以下操作:

#import inbuilt user model
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_profile(sender,**kwargs):
    # write you functionality
    pass

然后在初始文件中添加default_app_config

 default_app_config = "give your AppConfig path"