2016-01-31 67 views
3

我試圖在Transaction模型中添加所有total值,並將它們放在Sale模型的第一個實例(pk=1gross_total字段中。這是我的代碼。如何根據使用信號更新另一個模型的字段來更新模型字段?

models.py

class Sale(models.Model): 
    gross_total = models.FloatField() 

    def __unicode__(self): 
     return str(self.gross_total) 

class Transaction(models.Model): 
    sale = models.ForeignKey('Sale') 
    price = models.FloatField() 
    quantity = models.IntegerField() 
    total = models.FloatField(blank=True, null=True) 

    def save(self): 
     self.total = self.price * self.quantity 
     return super(Transaction, self).save() 

    def __unicode__(self): 
     return str(self.total) 

signals.py

from django.db.models.signals import post_save 
from django.dispatch import receiver 
from django.db.models import Sum 

from .models import Transaction, Sale 

@receiver(post_save, sender=Transaction) 
def update_sale(sender, **kwargs): 
    sale = Sale.objects.get(pk=1) 
    sale.gross_total = Transaction.objects.all().aggregate(Sum('total'))['total__sum'] 
    sale.save() 

我是新來使用Django的信號。我做錯了什麼?如果我保存Transaction模型的實例,則Sale模型數據不會更新!

+0

您是否導入了'signals.py'在'就緒()'函數在你的AppConfig中建議「這個代碼應該在哪裏住?」框中的文檔https://docs.djangoproject.com/en/1.9/topics/signals/#connecting-receiver-functions? – Nikita

+0

@Nikita我沒有那樣做。我已閱讀文檔中的信號章節,但對我來說不是很清楚。你能幫助這方面嗎? – MiniGunnR

+0

@Nikita好吧,我得到這個工作複製來自另一個博客的代碼,但我不知道它是如何工作的!你能給我一個簡單的閱讀材料嗎? – MiniGunnR

回答

2

我對我的應用程序進行了以下更改以使其正常工作。

__init__.py

default_app_config = 'alpha.apps.MyAppConfig' 

現在創建我的應用程序內的apps.py。

apps.py

from django.apps import AppConfig 

class MyAppConfig(AppConfig): 
    name = 'alpha' 
    verbose_name = 'Alpha' 

    def ready(self): 
     import alpha.signals 

我沒有任何想法,這一切是如何工作的,雖然在上海。

3

會發生什麼事是......

當你在編寫代碼signals.py這是一個有效的代碼,但它從來沒有運行,直到該模塊直接執行(在此情況下,預期的用途雖然)或進口。所以它必須被導入某個地方纔能運行代碼並且處理函數被註冊到相應的信號。

當您的Django項目運行時,Django從您的settings.py中聲明的應用程序創建應用程序註冊表。創建註冊表時,它會導入settings.py中聲明的每個包和模塊,並在此過程中調用幾個預定義函數,包括AppConfig內的ready()

當使用Python導入包時,特殊文件__init__.py中的代碼由Python內部自動執行,通常它允許爲包定義特殊行爲和屬性。

所以基本上,這導致:

  1. Django項目啓動。

  2. Django讀取settings.py並發現您的應用程序爲已聲明的應用程序之一。

  3. Django導入您的應用程序包,__init__.py中的代碼已運行,並且指定了default_app_config。現在Dgango知道它。

  4. 處理完所有應用程序後,Django會爲在前面步驟中找到的每個AppConfig調用ready()函數。

  5. ready() in MyAppConfig正在運行,您的signals.py模塊被導入。

  6. 在此導入過程中,將執行signals.py中的代碼:您的update_sale函數已創建,並且@receiver裝飾器以它作爲參數執行。

  7. 而正在執行寄存器update_sale函數receiver裝飾代碼作爲由Transaction模型類發射post_save信號運行。

相關問題