信号处理程序在哪里应该生活在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理。
希望这可以帮助!!