Django信号接收器接受self参数

2 投票
2 回答
1569 浏览
提问于 2025-04-17 08:36

我正在制作一个游戏。每当发生某个特定的动作时,就会发送一个信号。这个信号会被很多不同的对象使用。例如,玩家模型的实例会恢复一点生命值,而灯笼则会减少剩余的油量。我希望这些模型的实例在信号发出时能够做出反应并修改它们的数据。不过,我不知道在接收信号的函数中怎么引用实例本身,因为我不能把“self”放在函数的参数列表里。

class Lantern(models.Model):
    oil_left= models.IntegerField(default=4)

    @receiver(mySignal)
    def burn(sender, **kwargs):
        self.oil_left  -= 1 #<- self is not defined obviously
        self.save() #<- self is not defined obviously

为什么接收器要作为实例方法?因为在发送信号时,反应这个信号的实例列表是未知的。信号只是一个通知,告诉感兴趣的对象(也就是那些有接收方法的对象)发生了某个事件,这样它们就可以触发自己特定的行为。

2 个回答

0

信号并不是指你的模型对象类发生了变化,而是指在你每次对与模型相关的数据库表进行写入操作之前或之后需要做的一些事情。

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

@receiver(post_save, sender=YourModel)
def your_action_call(sender, instance, **kwargs):
   pass
   #some logic
1

你为什么想让信号成为一个实例方法呢?看起来没有什么特别的理由。你只需要确保在编写信号函数时,把相关的实例传进去,比如作为一个instance的关键字参数,就像内置的pre-savepost-save信号那样。

在问题编辑后添加 但这正是信号应该工作的方式。信号有一个单独的函数,它会发送信号和任何相关的信息,同时有多个接收者在监听这个信号。但是这些接收者本身并不和特定的实例关联——它们不能关联,因为实例只有在你真正创建它的时候才存在!否则它只是数据库中的一行数据。

也许你的接收函数可以自己查询相关的对象,然后在那儿更新它们——或者更好的是,直接做一个update查询来就地修改它们。

撰写回答