2012-10-22 3 views
44

Ich habe eine Frage zu Django.Django post_save() Signalimplementierung

I ManyToMany Models hier

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) 

Für 1 Warenkorb Objekt erstellt haben, kann ich so viele wie neue TransactionDetail Objekt (das Produkt und Menge) ein. Meine Frage ist. Wie kann ich den Trigger implementieren? Was ich möchte ist, wenn ein Transaktionsdetail erstellt wird, möchte ich, dass der Betrag des Produktbestands durch den Betrag im Transaktionsdetail subtrahiert wird.

Ich habe gelesen über post_save(), aber ich bin mir nicht sicher, wie man es implementiert. vielleicht so etwas wie dieses

wenn: post_save (TransactionDetail, Wagen) #Cart Objekt wo TransactionDetail.cart = Cart.id

Cart.stock -= TransactionDetail.amount 
+3

Sie werden wahrscheinlich in Rennbedingungen geraten, wenn Sie es so machen. –

Antwort

109

laufen Wenn Sie diese wirklich Signale verwenden möchten zu erreichen, hier ist kurz, wie,

+19

dieses Beispiel fehlt trotzend in der django docs –

+1

THis funktioniert gut für mich, aber weiß nicht, warum es in Schleife unbekannter Länge ist –

+3

Ich bekomme 'maximale Rekursion Tiefe überschritten 'Fehler, weil ich die Instanz selbst in der '@ Empfänger'-Funktion. Wie kann ich erreichen, dass ich Self-Models aktualisieren kann? Muss ich 'save()' Methode von Modellen überschreiben? – Dipak

10

Persönlich würde ich die TransactionDetail save() -Methode außer Kraft setzen und dort speichern die neue TransactionDetail und dann

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

Wenn Sie vermeiden möchten, maximum recursion depth exceeded zu bekommen, dann sollten Sie trennen Signale, bevor Sie innerhalb der Signal-Handler speichern. Das obige Beispiel (Kenny Shen Antwort), wäre dann:

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) 

Dies ist in Disconnect signals for models and reconnect in django, mit einem abstrakteren und nützlichen Beispiel gründlich beschrieben.

Siehe auch: https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals in der django docs.