如何使用信号更新其他模型的字段来更新模型字段?

时间:2016-01-31 06:02:36

标签: django signals

我正在尝试在total模型中添加所有Transaction值,并将它们放在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 Signals的新手。我做错了什么?如果我保存Transaction模型的实例,则Sale模型数据不会更新!

2 个答案:

答案 0 :(得分:3)

会发生什么......

当你在signals.py中编写代码时,它是一个有效的代码,但它永远不会运行,直到这个模块直接执行(在这种情况下不打算使用)或导入。因此必须在某处导入它才能运行代码并将处理函数注册到相应的信号。

当你的Django项目运行时,Django会根据settings.py中声明的应用程序创建应用程序注册表。在创建注册表时,它会导入settings.py中声明的每个包和模块,并在此过程中调用多个预定义函数,包括每个ready()内的AppConfig

在Python中导入包时,特殊文件__init__.py中的代码由Python内部自动执行,通常它允许为包定义特殊行为和属性。

基本上,这会导致:

  1. 启动Django项目。

  2. Django读取settings.py并将您的应用程序视为已声明的应用程序之一。

  3. Django导入您的App包,__init__.py内的代码已运行且指定了default_app_config。现在Dgango知道了。

  4. 当所有应用的处理完成后,Django会为之前步骤中找到的每{{}}}调用ready()函数。

  5. 运行AppConfig中的
  6. ready(),导入MyAppConfig模块。

  7. 在导入过程中,执行signals.py内的代码:创建signals.py函数,并以参数执行update_sale装饰器。

  8. 正在执行的@receiver装饰器代码寄存器receiver函数将在update_sale模型类发出的post_save信号上运行。

答案 1 :(得分:2)

我对我的应用进行了以下更改,以使其正常运行。

<强> __初始化__。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

我不知道这一切是怎么回事,哈哈。