D'après la documentation de Django que je lisais, il semble que signals.py
le dossier de l'application soit un bon point de départ, mais le problème auquel je suis confronté est que lorsque je crée des signaux pour pre_save
et que j'essaye d'importer la classe à partir du modèle, il entre en conflit avec le import
dans mon modèle.
# 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]
Ce code ne fonctionnera pas car j'importe à l' Comm_Queue
intérieur signals.py
et j'importe également les signaux à l'intérieur models.py
.
Quelqu'un peut-il me donner des conseils sur la façon dont je pourrais surmonter ce problème?
Cordialement
django
django-signals
Mo J. Mughrabi
la source
la source
Réponses:
Réponse originale, pour Django <1.7:
Vous pouvez enregistrer les signaux en les important
signals.py
dans le__init__.py
fichier de l'application :# __init__.py import signals
Cela permettra d'importer
models.py
depuissignals.py
sans erreurs d'importation circulaires.Un problème avec cette approche est qu'elle gâche les résultats de la couverture si vous utilisez coverage.py.
Discussion connexe
Edit: Pour Django> = 1.7:
Depuis l'introduction d'AppConfig, la méthode recommandée pour importer des signaux est dans sa
init()
fonction. Voir la réponse d'Eric Marcos pour plus de détails.la source
AppRegistryNotReady("Apps aren't loaded yet.")
Si vous utilisez Django <= 1.6, je vous recommande la solution Kamagatos: importez simplement vos signaux à la fin de votre module de modèles.
Pour les futures versions de Django (> = 1.7), la méthode recommandée est d'importer votre module de signaux dans la fonction config ready () de votre application :
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'
la source
doesn't declare an explicit app_label
Pour résoudre votre problème, il vous suffit d'importer signaux.py après la définition de votre modèle. C'est tout.
la source
J'ai également mis des signaux dans le fichier signaux.py et j'ai également cet extrait de code qui charge tous les signaux:
# 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)))
Ceci est pour le projet, je ne suis pas sûr que cela fonctionne au niveau de l'application.
la source
Dans les anciennes versions de Django, ce serait bien de mettre les signaux sur le
__init__.py
ou peut-être dans lemodels.py
(bien qu'à la fin, les modèles seront bien trop gros à mon goût).Avec Django 1.9, je pense qu'il vaut mieux placer les signaux sur un
signals.py
fichier et les importer avec leapps.py
, où ils vont être chargés après le chargement du modèle.apps.py:
from django.apps import AppConfig class PollsConfig(AppConfig): name = 'polls' def ready(self): from . import signals # NOQA
Vous pouvez également diviser vos signaux sur
signals.py
ethandlers.py
dans un autre dossier de votre modèle nommésignals
également, mais pour moi, c'est juste au-dessus de l'ingénierie. Jetez un œil à Placer des signauxla source
Je suppose que vous faites cela pour que vos signaux soient enregistrés, afin qu'ils soient trouvés quelque part. Je viens de mettre mes signaux directement dans un fichier models.py normalement.
la source
Cela ne s'applique que si vous avez vos signaux dans un
signals.py
fichier séparéTout à fait d'accord avec la réponse de @EricMarcos mais il faut préciser que la documentation django conseille explicitement de ne pas utiliser la variable default_app_config (bien que ce ne soit pas faux). Pour les versions actuelles, la manière correcte serait:
my_app / apps.py
from django.apps import AppConfig class MyAppConfig(AppConfig): name = 'my_app' def ready(self): import my_app.signals
settings.py
(Assurez-vous que vous n'avez pas seulement le nom de votre application dans les applications installées, mais plutôt le chemin relatif à votre AppConfig)
INSTALLED_APPS = [ 'my_app.apps.MyAppConfig', # ... ]
la source
Une alternative consiste à importer les fonctions de rappel depuis
signals.py
et à les connecter dansmodels.py
:signaux.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: l'importation
YourModel
danssignals.py
créera une récursivité; utilisezsender
plutôt.Ps2: la sauvegarde de l'instance à nouveau dans la fonction de rappel créera une récursivité. Vous pouvez créer un argument de contrôle dans
.save
method pour le contrôler.la source