Django pre_save信号无效

12 投票
4 回答
13998 浏览
提问于 2025-04-16 18:28

我测试了Django的“pre_save”信号,尝试了几种方法,但都没能捕捉到这个信号。

$

from django.db.models.signals import pre_save
import logging

def my_callback(sender, **kwargs):
    logging.debug("======================================")
pre_save.connect(my_callback)
  1. 我在manage.py的命令行中运行了上面的代码:然后我启动我的网站,发现models.save()正常工作,但回调函数没有运行。

  2. 另外,我再次在命令行中运行了上面的代码,然后在命令行中运行models.save()。这个“save”又正常工作了,但回调函数还是没有任何反应。

  3. 最后,我把上面的代码放进一个__init__.py文件里,然后在网站上运行save()函数。结果还是没有任何反应。

你能帮我找出为什么pre_save信号似乎不工作吗?

4 个回答

3

logging.debug() 是在使用根日志记录器,而这个记录器的处理级别默认是 30(也就是 'WARNING')。

=> logging.debug('something') 实际上什么都不会做(DEBUG 级别是 10,小于 30)。你可以查看 http://docs.python.org/2/library/logging.html 了解更多。

你可以用另一个自定义的日志记录器来做同样的测试,或者这样做:

l = logging.getLogger()
l.setLevel(10)
def my_callback(sender, **kwargs):
    logging.debug("======================================")
pre_save.connect(my_callback)

原来的问题没有提供足够的信息来判断这是否是提问者真正面临的问题(或者问题的一部分)。
但可以肯定的是,提问者的代码在我的 ./manage.py shell 中是无法工作的。

3

Eric的回答之所以能让事情正常运作,是因为他让你在models.py文件里连接了信号。这样,当你通过网站保存模型时,信号处理器和触发信号的地方是在同一个进程里。

在例子1和例子3中,很容易看出为什么它们不工作——因为你是在一个不同的进程(网站)中保存数据,而信号接收器却在另一个地方监听。

我希望我能更好地理解为什么例子2也出问题了,但我在自己的项目中调试信号时遇到了类似的问题,发现这肯定和信号发送者和接收者之间无法“看到”对方有关。

10

首先,你没有设置发送者的类。

from django.db.models.signals import pre_save
from myapp.models import MyModel
import logging

def my_callback(sender, **kwargs):
    logging.debug("======================================")
pre_save.connect(my_callback, sender=MyModel)

其次,如果你在用Django 1.3的话,应该使用新的装饰器语法。

# Inside your models.py
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver

class MyModel(models.Model):
    field1 = models.TextField()
    field2 = models.IntegerField()

@receiver(pre_save, sender=MyModel)
def mymodel_save_handler(sender, **kwargs):
    logging.debug("======================================")

这样应该就可以了,不过我没有测试过这个代码,所以如果还有问题请告诉我。

撰写回答