Opened 11 years ago
Closed 11 years ago
#21676 closed New feature (fixed)
Provide a way to run code when Django starts
Reported by: | Aymeric Augustin | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | Normal | Keywords: | app-loading |
Cc: | django@…, mmitar@… | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
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.
Change History (11)
comment:1 by , 11 years ago
Summary: | Provide a way to run code when a Django application starts → Provide a way to run code when Django starts |
---|
comment:2 by , 11 years ago
Description: | modified (diff) |
---|
comment:3 by , 11 years ago
comment:4 by , 11 years ago
In terms of API, jezdez and I just discussed the following:
- AppConfig.apps_ready() runs after apps are loaded; by default it's a noop.
- AppConfig.models_ready() runs after models are loaded; by default it calls AppConfig.ready() which is a noop.
Simple API: implement AppConfig.ready() (or .startup(), .configure()... The name must mean "just put your code there")
Advanced API: override .apps_ready() and .models_ready() (and don't forget to call super(), to ensure .ready() gets called eventually)
comment:5 by , 11 years ago
Cc: | added |
---|
comment:6 by , 11 years ago
Cc: | added |
---|
comment:7 by , 11 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:8 by , 11 years ago
Has patch: | set |
---|---|
Patch needs improvement: | set |
Mailing list discussion: https://groups.google.com/d/msg/django-developers/_iggZzrYtJQ/9Tzi-kmS8RsJ
Pull request: https://github.com/django/django/pull/2128
comment:9 by , 11 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Pull request is ready. Waiting for feedback on the mailing list.
comment:11 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Fixed in e187caa3afd7d292353fb32be1647da2cf0968da.
See also https://github.com/ptone/django/commit/de94a482d834539b9735d84afb2efdf31b8f0999.