Mo *_*abi 76 django django-signals
基于我正在阅读的Django文档,似乎signals.py
在app文件夹中是一个很好的开始,但我面临的问题是,当我创建信号时pre_save
,我尝试从模型中导入类,它与import
在我的模型中.
# models.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()
Run Code Online (Sandbox Code Playgroud)
# 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]
Run Code Online (Sandbox Code Playgroud)
此代码将无法运行,因为我导入Comm_Queue
内部signals.py
,我也导入内部信号models.py
.
任何人都可以就如何解决这个问题提出建议吗?
问候
Eri*_*cos 177
如果您使用的是Django <= 1.6,我建议使用Kamagatos解决方案:只需在模型模块的末尾导入信号.
对于Django的未来版本(> = 1.7),推荐的方法是在应用程序的config ready()函数中导入信号模块:
my_app/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
Run Code Online (Sandbox Code Playgroud)
my_app/__init__.py
default_app_config = 'my_app.apps.MyAppConfig'
Run Code Online (Sandbox Code Playgroud)
ypr*_*rez 61
您可以通过导入signals.py
应用程序的__init__.py
文件来注册信号:
# __init__.py
import signals
Run Code Online (Sandbox Code Playgroud)
这将允许models.py
从signals.py
没有循环导入错误导入.
这种方法的一个问题是,如果你使用的是coverage.py,它会混淆覆盖率结果.
自AppConfig推出以来,推荐的导入信号的方法就在于它的init()
功能.有关详细信息,请参阅 Eric Marcos的回答.
Kam*_*tos 25
要解决您的问题,您只需在模型定义后导入signals.py.就这样.
仅当您的信号位于单独的signals.py
文件中时,这才适用
完全同意@EricMarcos的答案,但应该指出的是,django文档明确建议不要使用default_app_config变量(尽管它没有错)。对于当前版本,正确的方法是:
my_app/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
Run Code Online (Sandbox Code Playgroud)
设置.py
(确保您在已安装的应用程序中不仅有您的应用程序名称,还有 AppConfig 的相对路径)
INSTALLED_APPS = [
'my_app.apps.MyAppConfig',
# ...
]
Run Code Online (Sandbox Code Playgroud)
我还将信号放在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)))
Run Code Online (Sandbox Code Playgroud)
这是针对项目的,我不确定它是否适用于应用程序级别.
在旧的 Django 版本中,可以将信号放在__init__.py
或 中models.py
(尽管最终模型对我来说会很大)。
对于 Django 1.9,我认为最好将信号放在signals.py
文件中并使用 导入它们,apps.py
加载模型后将在其中加载它们。
应用程序.py:
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'
def ready(self):
from . import signals # NOQA
Run Code Online (Sandbox Code Playgroud)
您还可以在模型内的另一个文件夹中signals.py
和handlers.py
中划分信号signals
,但对我来说这只是工程设计。看一下放置信号
归档时间: |
|
查看次数: |
26564 次 |
最近记录: |