This ticket is a subset of #3591 which can be dealt with independently. The following text summarizes discussions I've had with other core devs, mostly jezdez and ptone.

Nowadays Django has two common entry points:

1) wsgi.py, which calls django.core.wsgi.get_wsgi_application(). This triggers a few imports in Django, but not many, and it doesn’t import the project. As a consequence, settings are configured and the app registry is populated while serving the first request. get_wsgi_application() was introduced with the idea that it would be used to populate the app registry in the future.

2) manage.py, which calls django.core.management.execute_from_command_line(). Unless requires_model_validation has been set to False, this will quickly import and validate models, thus populating the app cache.

In addition, there’s an interesting entry point, or rather lack thereof:

3) DJANGO_SETTING_MODULE=myproject.settings python. It’s part of Django’s purity and we certainly want to preserve this ability.

There’s no way we can run an implement an initialization sequence in this third use case, so I’m leaving it aside. For comparison, with Rails, you can’t just start irb, you have to use script/console. The initialization process is daunting: ​http://guides.rubyonrails.org/initialization.html

So the most realistic option is to trigger startup code from get_wsgi_application() and execute_from_command_line(). The startup code would:

call apps.populate_apps() — rather than apps.populate_models()

for each application, call a conventional method on its configuration object, for instance AppConfig.startup()

It could be useful to provide a way to run code once models are loaded, probably with a second conventional method. (I'd like to avoid signals entirely.)

The documentation recommends defining the app config class in an app submodule. That avoids import issues that may happen when putting initialization code in the app's __init__.py. In the worst case, imports can be moved inside the startup() method.

This technique doesn't required changing manage.py and wsgi.py, which is important.