我刚刚开始在django项目中实现信号监听器。虽然我了解它们是什么以及如何使用它们。我很难弄清楚我应该把它们放在哪里。django网站上的文档说:
您可以将信号处理和注册代码放在您喜欢的任何位置。但是,您需要确保该模块所在的模块尽早导入,以便在需要发送任何信号之前注册信号处理。这使您的应用程序的models.py成为注册信号处理程序的好地方。
尽管这是一个很好的建议,但是在我的models.py中包含非模型类或方法只会给我带来错误的印象。
那么,存储和注册信号处理程序的最佳实践/规则是什么?
我刚刚开始在django项目中实现信号监听器。虽然我了解它们是什么以及如何使用它们。我很难弄清楚我应该把它们放在哪里。django网站上的文档说:
您可以将信号处理和注册代码放在您喜欢的任何位置。但是,您需要确保该模块所在的模块尽早导入,以便在需要发送任何信号之前注册信号处理。这使您的应用程序的models.py成为注册信号处理程序的好地方。
尽管这是一个很好的建议,但是在我的models.py中包含非模型类或方法只会给我带来错误的印象。
那么,存储和注册信号处理程序的最佳实践/规则是什么?
Answers:
我实际上喜欢使它们成为模型本身的分类方法。这将所有内容都保留在一个类中,这意味着您不必担心导入任何内容。
Foo它是的一部分fooapp。但是信号接收器是扩展程序,确实存在于其他应用程序中(例如otherapp)。
在Django 1.7发布时,它已添加到文档中:
严格来说,信号处理和注册代码可以存在于您喜欢的任何位置,尽管建议避免使用应用程序的根模块及其模型模块,以最大程度地减少导入代码的副作用。
实际上,信号处理程序通常是在与之相关的应用程序的信号子模块中定义的。信号接收器连接在应用程序配置类的ready()方法中。如果您使用的是receiver()装饰器,则只需将信号子模块导入ready()即可。
在Django 1.7中进行了更改:由于在早期版本的Django中不存在ready(),因此信号注册通常发生在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
通过直接在settings.py的INSTALLED_APPS或__init__应用的中指定它来确保您正在加载AppConfig 。有关更多信息,请参见ready()文档。
注意:如果您也要提供信号让其他应用程序也可以收听,请将它们放在__init__信号模块中的中,例如,如下文件:
yourapp / signals / __ 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()方法好,因为它经常会引起循环导入问题。
__init__导入信号的临时解决方法对我不起作用,所以我想知道在准备好升级到更高版本的Django之前,是否还有其他地方可以导入信号。
from . import handlers(或类似的)东西yourapp/signals/__init__.py吗?
yourproject.TaskConfig类代码块的最后一行。我已经使用了这种结构,因此请考虑以下问题:)
我只是碰到了这一点,由于我的信号与模型无关,所以我想添加自己的解决方案。
我正在登录/注销时记录各种数据,并且需要连接django.contrib.auth.signals。
我已经将信号处理程序放入signals.py文件中,然后从__init__.py模块文件中导入了信号,因为我相信应用程序启动后就会立即调用该信号(使用print语句进行测试表明,即使在读取设置文件之前也会调用该信号。)
# /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)很陌生,所以欢迎任何告诉我这是一个糟糕主意的人!
user_logged_in.connect(on_logged_in)应该很可能会传递dispatch_uid参数。有关更多信息,请访问docs.djangoproject.com/en/dev/topics/signals/…。
最近,我刚刚读了这篇关于最佳实践的文章,其中涉及到布置您的项目/应用程序的过程,并且建议您将所有自定义调度程序信号都放在一个名为的文件中signals.py。但是,这并不能完全解决您的问题,因为您仍然需要将它们导入某个位置,并且越早导入它们越好。
模型建议是一个很好的建议。由于您已经定义了signals.py文件中的所有内容,因此文件顶部最多只需要一行。这类似于admin.py文件的布局方式(顶部是类定义,底部是用于注册所有自定义管理类的代码),如果您定义了信号,则将它们连接到同一文件中。
希望有帮助!最终,它取决于您的偏好。
signals.py文件中,但不知道随后如何调用它。通过将其导入到我的models.py文件中,我得到了一个非常干净的解决方案,而没有“污染”我的models.py文件。谢谢!:)
在每个应用程序中,models.py和signals.py都是连接信号的建议位置,但是,我认为,这不是保持信号和处理程序派发的最佳解决方案。调度应该是django中发明的信号和处理程序的原因。
我苦苦挣扎了很长时间,最后我们找到了解决方案。
在应用程序文件夹中创建连接器模块
所以我们有:
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。模型和信号没有混乱。
希望它提供另一个解决方案。
signals.py在models.py定义所有模型之后,我将它们保存在单独的文件中。我导入它们并将模型连接到信号。
signal.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中当然没有错 ,但是这种方式更易于管理。
希望这可以帮助!!