Search code examples
djangodjango-signals

registering signals in Django results in "Apps aren't loaded yet." error


I keep getting the error, when trying to import signals:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

I can't understand this, b/c I've used the following pattern successfully when setting up a user profile in other apps:

models.py:

from django.conf import settings
from django.db import models

class UserProfile(models.Model):
  user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    

signals.py:

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from my_project.my_app.models import UserProfile

def post_save_user_hander(sender, *args, **kwargs):
     created = kwargs.get("created", False)
     instance = kwargs.get("instance", None)
     if created and instance:
         UserProfile.objects.create(user=instance)


post_save.connect(
    post_save_user_hander, 
    sender=get_user_model(),
    dispatch_uid="post_save_user_handler",
)

app.py:

from django.apps import AppConfig

class MyAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'my_project.my_app'

    try:
        import my_project.my_app.signals  
    except ImportError:
        pass

According to the documentation, ready() is called "as soon as the registry is fully populated". Therefore, shouldn't the import of UserProfile succeed? Also, the documentation states

Although you can’t import models at the module-level where AppConfig classes are defined, you can import them in ready(), using either an import statement or get_model().

Therefore, including them at the top of signals.py which is itself imported in ready() should work, right?


Solution

  • Try to include signals in AppConfig.ready method.

    from django.apps import AppConfig
    
    
    class MyAppConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        name = 'my_project.my_app'
    
        def ready(self):
            import my_project.my_app.signals
    

    From docs on AppConfig.ready

    Subclasses can override this method to perform initialization tasks such as registering signals. It is called as soon as the registry is fully populated.

    If you’re registering model signals, you can refer to the sender by its string label instead of using the model class itself.

    So, I suppose it's a common approach to include signals in AppConfig.ready method.