繁体   English   中英

Django post_save() 信号实现

[英]Django post_save() signal implementation

我有一个关于 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

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

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

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

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

如果您想避免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

如果你真的想在 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"

事实上,docstrstring 解释了Signalsdjango.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.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM