Django post_syncdb信号处理器未被调用?

3 投票
3 回答
3055 浏览
提问于 2025-04-16 08:15

我有一个 myapp/management/__init__.py 文件,它在里面注册了一个 post_syncdb 的处理器,像这样:

from django.db.models import signals
from features import models as features

def create_features(app, created_models, verbosity, **kwargs):
    print "Creating features!"
    # Do stuff...

signals.post_syncdb.connect(create_features, sender=features)

我确认了以下几点:

  1. 两个应用 featuresmyapp 都在 settings.INSTALLED_APPS 列表里
  2. myapp.management 在执行 syncdb 之前就已经加载了(我通过在模块级别加了一个打印语句来确认)
  3. features 应用在 syncdb 处理时被处理,并且它发出了 post_syncdb 的信号(我通过查看 syncdb 的输出,使用了 --verbosity=2 来确认)
  4. 我对另外一对应用使用了完全相同的方式,那个处理器能正常调用。我对比了这两个模块,发现它们在调用上没有相关的区别。

但是,myapp.management.create_features 从来没有被调用。我遗漏了什么呢?

3 个回答

0

关键在于 sender。你的自定义回调函数只有在 sender 成功执行时才会被调用。在我的情况下,senderdb.models,而当 syncdb 不是第一次调用时,它就不会成功,也就是说,数据库中已经存在同步过的模型。文档里有提到这一点,但没有强调清楚。

sender

刚刚安装的模型模块。也就是说,如果 syncdb 刚刚安装了一个叫 "foo.bar.myapp" 的应用,那么 sender 就是 foo.bar.myapp.models 模块。

所以我的解决办法是删除数据库,然后重新安装我的应用。

1

我刚遇到同样的问题,我的解决办法是把函数参数中的 sender 去掉,然后在回调函数里面检查它。

from django.db.models import signals
from features import models as features

def create_features(app, created_models, verbosity, **kwargs):
    print "Creating features!"
    if app != features #this will work as it compares models module instances
        return
    # Do stuff...

signals.post_syncdb.connect(create_features)

这样你就可以像Django文档里建议的那样,把它们放在你的管理模块里。我同意你的想法,它应该像你说的那样工作。你可以深入研究一下 django.dispatch 里的 Signal 类的实现。

3

试着把它放到你的 models.py 文件里。

撰写回答