信号处理程序在哪里应该生活在Django项目?

我刚刚开始在django项目中实现信号侦听器。 虽然我明白他们是什么以及如何使用他们。 我很难搞清楚我应该把它们放在哪里。 django网站的文档有这样的说法:

这个代码应该在哪里居住?

你可以把信号处理和注册码放在任何你喜欢的地方。 但是,您需要确保它所在的模块得到早期导入,以便在需要发送任何信号之前,信号处理得到注册。 这使得您的应用程序的models.py是注册信号处理程序的好地方。

虽然这是一个很好的build议,但在我的models.py中使用非模型类或方法只是歪曲了我。

那么,存储和注册信号处理程序的最佳实践/规则是什么?

我其实喜欢让他们模式本身的类方法。 这使得一切都在一个类中,并且意味着您不必担心导入任何内容。

Django 1.7发布时,它被添加到文档中 :

严格来说,信号处理和注册码可以在任何你喜欢的地方生存,尽pipebuild议避免应用程序的根模块及其模型模块,以尽量减less导入代码的副作用。

实际上,信号处理程序通常定义在与其相关的应用程序的信号子模块中。 信号接收器连接在应用程序configuration类的ready()方法中。 如果使用receiver()装饰器,只需将ready()中的信号子模块导入即可。

在Django 1.7中更改:由于ready()在以前的Django版本中不存在,因此信号注册通常发生在models模块中。

最佳做法是在信号子模块的handlers.py中定义处理程序,例如:

yourapp / signals / handlers.py

from django.db.models.signals import pre_save from django.dispatch import receiver from myapp.models import MyModel @receiver(pre_save, sender=MyModel) def my_handler(sender, **kwargs): pass 

然后,使用ready()方法在注册信号处理程序的最佳位置是定义它的应用程序的AppConfig中。 这看起来像这样:

yourapp / apps.py

 from django.apps import AppConfig class TasksConfig(AppConfig): name = 'tasks' verbose_name = "Tasks" def ready(self): import yourproject.yourapp.signals.handlers #noqa 

请确保您正在加载您的AppConfig,方法是直接在您的settings.py的INSTALLED_APPS或您的应用程序的__init__中指定它。 请参阅ready()文档以获取更多信息。

注意:如果您为其他应用程序提供的信号也要监听,请将它们放入信号模块的__init__中,例如:

yourapp /信号/ __ init__.py

 import django.dispatch task_generate_pre_save = django.dispatch.Signal(providing_args=["task"]) 

然后,另一个应用程序可以通过导入和注册信号,例如from yourapp.signals import task_generate_pre_save来听取您的信号。 从你的处理程序分离你的信号保持干净。

Django 1.6的说明:

如果你仍然停留在Django 1.6或更低版本,那么你会做同样的事情(在yourapp / signals / handlers.py中定义你的处理程序),而不是使用AppConfig,你可以通过__init__.py来加载处理程序。你的应用程序,例如:

yourapp / __ init__.py

 import signals 

这不如使用ready()方法好,因为它经常会导致循环导入问题。

我只是遇到了这个,因为我的信号不是模型相关的,我想我会添加我的解决scheme。

我login/注销日志logging各种数据,并需要钩入django.contrib.auth.signals

我已经把信号处理程序放到了一个signals.py文件中,然后从__init__.py模块文件中导入信号,因为我相信这个应用程序一启动就会被调用(使用print语句testing表明它甚至在调用之前被调用读取设置文件。)

 # /project/__init__.py import signals 

和signals.py

 # /project/signals.py from django.contrib.auth.signals import user_logged_in def on_logged_in(sender, user, request, **kwargs): print 'User logged in as: \'{0}\''.format(user) user_logged_in.connect(on_logged_in) 

我对Django很新(/ python),所以我向任何告诉我这是一个可怕的主意的人开放!

我最近刚刚阅读这篇关于最佳实践的文章,说明您的项目/应用程序的布局,并build议您所有的自定义调度程序信号都应放在名为signals.py的文件中。 但是,这并不能完全解决你的问题,因为你仍然需要导入这些地方,而且越早导入就越好。

模型build议是一个很好的。 由于您已经在signals.py文件中定义了所有内容,因此不应该在文件顶部占用更多行。 这与admin.py文件的布局方式类似(在顶部使用类定义,在底部使用用于注册所有自定义pipe理类的代码),如果您定义了信号然后将它们连接到同一个文件中。

希望有所帮助! 最终归结为你喜欢的东西。

在每个应用程序中的models.py和signals.py都是连接信号的推荐位置,但是,在我看来,它们并不是最好的解决scheme,以保持信号和处理程序的调度。 调度应该是django发明信号和处理程序的原因。

我挣扎了很长时间,最后我们find了解决办法。

在app文件夹中创build一个连接器模块

所以我们有:

 app/ __init__.py signals.py models.py connectors.py 

在app / connectors.py中,我们定义了信号处理程序并连接它们。 提供了一个例子:

 from signals import example_signal from models import ExampleModel from django.db.models.signals import post_save, post_delete def hanndler(sender, *args, **kwargs): pass post_save.connect(hander, sender=ExampleModel) 

然后在models.py中,我们在文件末尾添加以下行:

 from app import connector 

一切在这里完成。

通过这种方式,我们可以将signals.py中的信号以及connectors.py中的所有处理程序。 没有在模型和信号混乱。

希望它提供另一个解决scheme

我把它们放在单独的文件signals.py ,在models.py中定义好所有的模型。 我导入它们并将模型连接到信号。

signals.py

 # necessary imports def send_mail_on_save(<args>): # code here 

models.py

 # imports class mymodel(models.Model): # model here # import signals from signals import send_mail_on_save # connect them post_save.connect(send_mail_on_save,sender=mymodel) 

这给我提供了逻辑上的分离,当然把它们保存在models.py中没有什么错,但是这样更容易pipe理。

希望这可以帮助!!