Com base na documentação do Django que eu estava lendo, parece que signals.py
a pasta do app é um bom lugar para começar, mas o problema que estou enfrentando é que quando eu crio sinais para pre_save
e tento importar a classe do modelo, ela entra em conflito com o import
no meu modelo.
# 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()
# 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]
Este código não será executado porque eu importo Comm_Queue
dentro signals.py
e também importo os sinais dentro models.py
.
Alguém pode me aconselhar sobre como eu poderia superar esse problema?
Saudações
django
django-signals
Mo J. Mughrabi
fonte
fonte
Respostas:
Resposta original, para Django <1.7:
Você pode registrar os sinais importando
signals.py
no__init__.py
arquivo do aplicativo :# __init__.py import signals
Isso permitirá a importação
models.py
designals.py
sem erros de importação circulares.Um problema com essa abordagem é que ela bagunça os resultados da cobertura se você estiver usando o cover.py.
Discussão relacionada
Editar: Para Django> = 1,7:
Desde que o AppConfig foi introduzido, a forma recomendada de importar sinais está em sua
init()
função. Veja a resposta de Eric Marcos para mais detalhes.fonte
AppRegistryNotReady("Apps aren't loaded yet.")
Se você estiver usando Django <= 1.6, eu recomendo a solução Kamagatos: basta importar seus sinais no final do módulo de seus modelos.
Para versões futuras do Django (> = 1.7), a maneira recomendada é importar seu módulo de sinais na função config ready () do seu aplicativo :
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'
fonte
doesn't declare an explicit app_label
.Para resolver o seu problema, basta importar o signs.py após a definição do seu modelo. Isso é tudo.
fonte
Eu também coloco sinais no arquivo signs.py e também tenho este snippet de código que carrega todos os sinais:
# 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)))
Isso é para projeto, não tenho certeza se funciona no nível do aplicativo.
fonte
Em versões antigas do Django, seria bom colocar os sinais no
__init__.py
ou talvez nomodels.py
(embora no final os modelos sejam muito grandes para o meu gosto).Com Django 1.9, acho melhor colocar os sinais em um
signals.py
arquivo e importá-los com oapps.py
, onde eles serão carregados após carregar o modelo.apps.py:
from django.apps import AppConfig class PollsConfig(AppConfig): name = 'polls' def ready(self): from . import signals # NOQA
Você também pode dividir seus sinais em
signals.py
ehandlers.py
em outra pasta dentro do seu modelo nomeadosignals
também, mas para mim isso é apenas mais engenharia. Dê uma olhada em Colocando Sinaisfonte
Suponho que você esteja fazendo isso para que seus sinais sejam registrados, de modo que sejam encontrados em algum lugar. Acabei de colocar meus sinais em um arquivo models.py normalmente.
fonte
Isso só se aplica se você tiver seus sinais em um
signals.py
arquivo separadoConcordo totalmente com a resposta de @EricMarcos, mas deve ser declarado que a documentação do django aconselha explicitamente não usar a variável default_app_config (embora não esteja errada).Para as versões atuais, a maneira correta seria:
my_app / apps.py
from django.apps import AppConfig class MyAppConfig(AppConfig): name = 'my_app' def ready(self): import my_app.signals
settings.py
(Certifique-se de não ter apenas o nome do seu aplicativo nos aplicativos instalados, mas também o caminho relativo para o seu AppConfig)
INSTALLED_APPS = [ 'my_app.apps.MyAppConfig', # ... ]
fonte
Uma alternativa é importar as funções de retorno de chamada
signals.py
e conectá-las emmodels.py
:sinais.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: Importando
YourModel
emsignals.py
criará uma recursão; usarsender
, em vez disso.Ps2: Salvar a instância novamente na função de retorno de chamada criará uma recursão. Você pode fazer um argumento de controle no
.save
método para controlá-lo.fonte