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