Подтвердить что ты не робот

Реализация сигнала 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) #Cart object where TransactionDetail.cart= Cart.id
Cart.stock -= TransactionDetail.amount
4b9b3361

Ответ 1

Если вы действительно хотите использовать сигналы для достижения этого, здесь кратко, как,

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

Ответ 2

Лично я бы переопределил метод TransactionDetail save() и там сохранил новый TransactionDetail, а затем запустил

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

Ответ 3

Если вы хотите избежать 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 для моделей и переподключения в django, с более абстрактным и полезным примером.

Также см. Https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals в документации django.

Ответ 4

django.dispatch.Signal.connect, документ, объясняющий 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.