web-dev-qa-db-fra.com

Django post_save () implémentation du signal

J'ai une question à propos de Django.

J'ai de nombreux modèles ici

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)

Pour 1 objet panier créé, je peux en insérer autant qu'un nouvel objet TransactionDetail (le produit et le montant). Ma question est. Comment puis-je implémenter le déclencheur? Ce que je veux, c'est que chaque fois qu'un détail de transaction est créé, je souhaite que le montant du stock du produit soit soustrait du montant figurant dans le détail de la transaction.

J'ai lu sur post_save () mais je ne sais pas comment l'implémenter. peut-être quelque chose comme ça

quand:

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

Si vous voulez vraiment utiliser des signaux pour y parvenir, voici brièvement comment,

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()
141
Kenny Shen

Personnellement, je remplacerais la méthode save () de TransactionDetail, puis enregistrerais le nouveau TransactionDetail, puis exécuter

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

Si vous voulez éviter d’obtenir maximum recursion depth exceeded, vous devez déconnecter les signaux avant de les enregistrer dans le gestionnaire de signaux. L'exemple ci-dessus (réponse de Kenny Shen) serait alors:

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)

Ceci est décrit en détail dans Déconnectez les signaux des modèles et reconnectez-vous dans Django , avec un exemple plus abstrait et utile.

Voir aussi: https://docs.djangoproject.com/fr/2.0/topics/signals/#disconnecting-signals dans le Django docs.

5
Guglielmo Celata

En fait, le document expliquant le Signals se trouve dans 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.
2
Zulu