2012-10-22 28 views
44

Mam pytanie dotyczące django.Django post_save() implementacja sygnału

Mam ManyToMany modele tutaj

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) 

za 1 koszyka utworzonego obiektu, mogę wstawić aż nowego obiektu TransactionDetail (produktu i ilości). Moje pytanie brzmi. Jak mogę zaimplementować wyzwalacz? To, czego chcę, to to, kiedy tworzony jest szczegół transakcji, chcę, aby kwota zapasów produktu została odjęta o kwotę w danych transakcyjnych.

Przeczytałem o post_save(), ale nie jestem pewien, jak go zaimplementować. może coś takiego

gdy: post_save (TransactionDetail, Cart) #Cart sprzeciw gdzie TransactionDetail.cart = Cart.id

Cart.stock -= TransactionDetail.amount 
+3

Prawdopodobnie natkniesz się na warunki wyścigu, jeśli zrobisz to w ten sposób. –

Odpowiedz

109

Jeśli naprawdę chcesz używać sygnałów do osiągnięcia tego celu, oto jak krótko,

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

ten przykład jest zdecydowanie brakuje w dokumentacji Django –

+1

To działa dobrze dla mnie, ale nie wiem, dlaczego jest w pętli nieznanej długości –

+3

Otrzymuję błąd "maksymalna głębokość rekursji przekroczył", ponieważ byłem zapisywanie samej instancji w Funkcja '@ receiver'. Jak mogę dokonać aktualizacji modeli własnych? Czy muszę nadpisywać metodę "save()" modeli? – Dipak

10

Osobiście przesłonić TransactionDetail za save() metody i tam zapisać nowa TransactionDetail a następnie uruchomić

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

Aby uniknąć pobierania maximum recursion depth exceeded, należy odłączyć odłączyć sygnały, przed zapisaniem w programie obsługi sygnału. Powyższy przykład (odpowiedź Kenny Shen'a), by następnie być:

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) 

To jest dokładnie opisany w Disconnect signals for models and reconnect in django, o bardziej abstrakcyjnej i użyteczny przykład.

Zobacz także: https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals w dokumentach django.

Powiązane problemy