将我的signals.py文件保存在django中的正确位置

基于我从django网站阅读的文档,它似乎像应用程序文件夹中的signals.py是一个很好的开始,但是我面临的问题是,当我为pre_save创build信号,我尝试导入类从模型,与模型中任务的导入操作冲突。 看到我的代码如下

model.py

from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext as _ from signals import * class Comm_Queue(CommunicatorAbstract): queue_statuses = ( ('P', _('Pending')), ('S', _('Sent')), ('E', _('Error')), ('R', _('Rejected')), ) status = models.CharField(max_length=10, db_index=True, default='P') is_html = models.BooleanField(default=False) language = models.CharField(max_length=6, choices=settings.LANGUAGES) sender_email = models.EmailField() recipient_email = models.EmailField() subject = models.CharField(max_length=100) content = models.TextField() 

signals.py

 from django.conf import settings from django.db.models.signals import pre_save from django.dispatch import receiver from models import Comm_Queue @receiver(pre_save, sender=Comm_Queue) def get_sender_email_from_settings(sender, **kwargs): obj=kwargs['instance'] if not obj.sender_email: obj.sender_email='%s' % settings.ADMINS[0][1] 

这段代码将不会运行,因为我在信号里面导入了Comm_queue,并且正在执行*导入到models.py中的信号。 可以任何一个build议,我怎么能过来这个问题?

问候,

Django的原始答案<1.7:

您可以通过在应用程序的__init__.py文件中导入signals.py来注册信号:

 # __init__.py import signals 

这将允许从signals.py导入models.py而没有循环导入错误。

这种方法存在的一个问题是,如果使用coverage.py,则会掩盖覆盖率结果。

相关讨论

编辑:对于Django> = 1.7:

自引入AppConfig以来,推荐的导入信号的方式就是init()函数。 请参阅Eric Marcos的答案以获取更多详细信息。

如果您使用的是Django <= 1.6,我build议您使用Kamagatos解决scheme:只需在模型的最后input信号。

对于未来版本的Django(> = 1.7), 推荐的方法是在应用程序的config ()函数中导入你的signals模块:

my_app/apps.py

 from django.apps import AppConfig class MyAppConfig(AppConfig): name = 'my_app' def ready(self): import my_app.signals 

my_app/__init__.py

 default_app_config = 'my_app.apps.MyAppConfig' 

为了解决你的问题,你只需要在模型定义之后导入signals.py。 就这样。

我也把信号放在signals.py文件中,也有这个加载所有信号的代码片段:

 # import this in url.py file ! import logging from importlib import import_module from django.conf import settings logger = logging.getLogger(__name__) signal_modules = {} for app in settings.INSTALLED_APPS: signals_module = '%s.signals' % app try: logger.debug('loading "%s" ..' % signals_module) signal_modules[app] = import_module(signals_module) except ImportError as e: logger.warning( 'failed to import "%s", reason: %s' % (signals_module, str(e))) 

这是项目,我不知道它是否在应用程序级别上工作。

我猜你正在这样做,所以你的信号被注册了,所以他们被发现的地方。 我只是把我的信号正确地在一个models.py文件。

在旧的Django版本中,将信号放在__init__.py或者models.py (尽pipe最终模型将会以我的口味为大)。

在Django 1.9中,我认为将信号放置在一个apps.py文件中,然后将它们与apps.py一起导入,在加载模型之后将会加载它们。

apps.py:

 from django.apps import AppConfig class PollsConfig(AppConfig): name = 'polls' def ready(self): from . import signals # NOQA 

您也可以将signals.pyhandlers.py分配到您的模型命名signals中的另一个文件夹中,但是对于我来说这只是工程。 看看放置信号

另一种方法是从signals.py导入callback函数,并将它们连接到models.py

signals.py

 def pre_save_callback_function(sender, instance, **kwargs): # Do stuff here 

model.py

 # Your imports here from django.db.models.signals import pre_save from yourapp.signals import pre_save_callback_function class YourModel: # Model stuff here pre_save.connect(pre_save_callback_function, sender=YourModel) 

Ps:在YourModel中导入YourModel会创build一个recursion; 使用sender ,而不是。

Ps2:在callback函数中再次保存实例将创build一个recursion。 你可以在.save方法.save一个控制参数来控制它。