2012-10-22 2 views
44

장고에 대한 질문이 있습니다. Django post_save() 신호 구현

은 내가 만든 1 카트 목적은 여기를

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) 

ManyToMany 모델을 가지고, 나는 새로운 TransactionDetail 개체 (제품 및 금액)만큼을 삽입 할 수 있습니다. 내 질문은. 방아쇠를 어떻게 구현할 수 있습니까? 내가 원하는 것은 거래 세부 사항이 생성 될 때마다, 나는 제품의 재고 금액을 transactiondetail의 금액으로 뺀 것을 원한다.

post_save()에 대해 읽었지만 구현 방법을 잘 모르겠습니다. 어쩌면이

같은 때 : post_save (TransactionDetail, 장바구니) TransactionDetail.cart = Cart.id

Cart.stock -= TransactionDetail.amount 
+3

이렇게하면 경주에 빠질 가능성이 큽니다. 나는의 인스턴스 자체를 저장했기 때문에 –

답변

109

을 실행은

, 간단히 방법
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

이 예 도전적이 나를 위해 잘 작동하지만 알 수없는 길이 내가'최대 재귀 깊이 exceeded' 오류가 발생하고 –

+1

에 없습니다 '@ 수신기 '기능. 자체 모델을 업데이트하려면 어떻게해야합니까? 모델의'save()'메소드를 오버라이드해야합니까? –

+3

의 루프에서 왜 모르는 장고 문서 – Dipak

10

가 개인적으로 나는 TransactionDetail의 저장() 메소드를 오버라이드 (override) 할 경우 객체와 거기에 저장 #Cart 새로운 TransactionDetail 당신은 정말이를 달성하기 위해 신호를 사용하려면 여기에,

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

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 signals for models and reconnect in django에 철저하게 설명되어 있습니다.

또한 참조 : 장고 문서에 https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals.

관련 문제