Search code examples
djangodjango-signals

The right place to keep my signals.py file in a Django project


Based on Django's documentation I was reading, it seems like signals.py in the app folder is a good place to start with, but the problem I'm facing is that when I create signals for pre_save and I try to import the class from model it conflicts with the import in my model.

# 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]

This code will not run because I import Comm_Queue inside signals.py and I also import the signals inside models.py.

Can anyone advice on how I could over come this issue?

Regards


Solution

  • Original answer, for Django < 1.7:

    You can register the signals by importing signals.py in the app's __init__.py file:

    # __init__.py
    import signals
    

    This will allow to import models.py from signals.py without circular import errors.

    One problem with this approach is that it messes up the coverage results if you're using coverage.py.

    Related discussion

    Edit: For Django >= 1.7:

    Since AppConfig was introduced, the recommended way of importing signals is in its init() function. See Eric Marcos' answer for more details.