Django post_保存()信号实现

qcuzuvrc  于 2023-04-07  发布在  Go
关注(0)|答案(5)|浏览(104)

我有个关于 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对象(产品和金额)。我的问题是。我如何实现触发器?我想要的是每当创建Transaction明细时,我希望产品的库存金额减去transactiondetail中的金额。
我读过关于post_保存()的文章,但是我不确定如何实现它。
当:

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

9rnv2umw1#

如果你真的想使用信号来实现这一点,这里简要介绍了如何,

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

w80xi6nr2#

就我个人而言,我会覆盖TransactionDetail的保存()方法,并在其中保存新的TransactionDetail,然后运行

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

k2arahey3#

如果你想避免得到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中有详细的描述,其中有一个更抽象和有用的示例。
另请参阅:https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signalsin the django docs.

cwtwac6a

cwtwac6a4#

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

然后在init文件中添加default_app_config

default_app_config = "give your AppConfig path"
llew8vvj

llew8vvj5#

事实上,文档字符串解释了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.

相关问题