Load signals automatically

Hi guys !

First of all, i’m new here, so if this issue has already been discussed or if here is not the place to talk about it please don’t hesitate to tell me. Also, please be aware English is not my first language.

I would want to discuss about signals and how they are loaded in Django.

Very often, i create my signals.py, write my signal and wonder for a while why it does not work. Of course, the file is not imported and so never even read by python !
So i create an apps.py, on this template :

from django.apps import AppConfig


class CustomAppConfig(AppConfig):
    name = "app.subapp"

    def ready(self):
        import app.subapp.signals

I would like to sugest importing signals.py automatically at app loading (maybe django.apps.config.AppConfig.ready() ?)

Pros

  • no more wandering for hours what is the problem here
  • no more boilerplate apps.py everywhere

Cons

  • file with signals would have to be named signals.py
  • maybe some rely on the file being imported when they decided ? (don’t see a use case here, specially when loading signals does not equals activating them)

Alternatives

If loading (and so activating) signals is too mush of a change, maybe others solutions will fix my problem. For know, all I can think of :

  • Log if a signals.py file is detected but the AppConfig is not overriden (but we would not know if imported elsewhere)
  • Log how many signals are detected for the app (but from a dozen apps the log will be too heavy to be read)
  • not really an alternative, but the loading could be conditionnal to a project-wide setting

i would like to know if this would benefits others (I think so) and if it is worthy of filing an Issue

1 Like

Hi Roxane

By “signals” I understand your signal receivers, i.e. functions passed to Signal.connect().

To automatically load all apps’ signal receivers from signals submodules, you can include code like this in any of your AppConfig.ready() methods:

from importlib import import_module
from django.apps import apps

for app_config in apps.get_app_configs():
    base = app_config.module.__name__
    try:
        import_module(f"{base}.signals")
    except ImportError:
        pass

If that’s what you’re looking for, you can at least add it to your project.

Personally I don’t find making the import automatic particularly necessary. Automatically loading particular app submodules is a bit “unpythonic” and “magic”. Django does it for three cases at the moment - apps, models, and admin - but I would not really be in favour of extending that list. Python doesn’t automatically load all submodules when a package is imported, and we don’t want Django users to gain the wrong mental model here. Moreover it’s useful to avoid loading code in certain circumstances.

To avoid confusion I always write my Signal.connect() calls etc. in my AppConfig.ready(), rather than at the module level in a separate module. Here’s an example registering a system check (similar to connecting a signal receiver).

On the use of signals - they should be avoided for calls between apps in your project. It’s clearer for reading and debugging to use plain old function calls. See the “When to use custom signals” note at Signals | Django documentation | Django .

Hope that helps!

Hi Adam.

Thank you for your response., i see what you mean.

Speaking of documentation, could we consider expaning the “Where should this code live?” note ? Maybe make it its own sub-article, or including a code snippet ?

I would understand if this is regarded as an issue we can resolve like a grown-up : search engine into stackoverflow works well, after all ; In which case we can close this issue

Regards, Roxane.

I’d be happy to review a PR. It could be expanded with a code sample of AppConfig.ready().

Aaaaand here it is !

1 Like