84

我有一个关于 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() 但我不知道如何实现它。也许是这样的

什么时候:

post_save(TransactionDetail, 
       Cart) #Cart object where TransactionDetail.cart= Cart.id
Cart.stock -= TransactionDetail.amount
4

5 回答 5

179

如果您真的想使用信号来实现这一点,这里简要介绍一下方法,

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

class TransactionDetail(models.Model):
    product = models.ForeignKey(Product)

# 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()
于 2012-10-22T17:56:24.157 回答
20

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

self.product.stock -= self.amount
self.product.save()
于 2012-10-22T17:14:13.810 回答
17

如果你想避免得到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

于 2017-12-28T12:07:48.147 回答
4

如果你真的想在 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"
于 2019-10-23T05:37:51.520 回答
2

事实上,docstrstring 解释了Signalsis in 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.
于 2018-11-08T04:33:37.123 回答