The age old question of "How do I run code when Django starts?" may now be finally answered.
Django 1.4 made a big improvement with how Django is started. The {{{manage.py}}} script has been simplified and made more explicit. This allows for better customization of the bootstrap process of Django and your project.
A common question in the Django community is "how do I run some code at start up?" The best way to implement this is to simply run some code at the entry points of Django (after we ensure {{{DJANGO_SETTINGS_MODULE}}} is set.) These entry points are: {{{manage.py}}} and {{{wsgi.py}}}.
The {{{manage.py}}} script is the most common entry point in development, but can also be used to start production role code. The {{{wsgi.py}}} script is used to interface with WSGI servers.
In Pinax we've set out to solve this issue and provide a common place that you can guarantee will be run during the start up of Django. One of the most common tasks is to register signals. A workaround is to register them through {{{urls.py}}}, but this isn't ideal and can cause problems.
The solution is really simple. Using project template code here is how entry points may look.
{{{manage.py}}}:
{{{ #!code python import os import sys
if name == "main": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
import {{ project_name }}.startup as startup
startup.run()
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
}}}
{{{wsgi.py}}}:
{{{ #!code python import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
import {{ project_name }}.startup as startup startup.run()
from django.core.wsgi import get_wsgi_application application = get_wsgi_application() }}}
This will import a {{{startup.py}}} file located in your project's package. The only requirement is that you define the {{{run}}} method. In Pinax we decided to take it a little bit further. Since registering signals is a common task to do we wrote a utility function we put in our {{{startup.py}}}:
{{{ #!code python from django.conf import settings from django.utils.importlib import import_module from django.utils.module_loading import module_has_submodule
def autoload(submodules): for app in settings.INSTALLED_APPS: mod = import_module(app) for submodule in submodules: try: import_module("{}.{}".format(app, submodule)) except: if module_has_submodule(mod, submodule): raise
def run(): autoload(["receivers"]) }}}
Now, when Django starts up all app's {{{receivers.py}}} are imported ensuring they get registered at the appropriate time. No more {{{urls.py}}} or {{{models.py}}} hacks.
This approach now ships with all Pinax projects. You can check out the starter projects on the [[https://github.com/pinax|Pinax Github account]]. Look for repositories beginning with {{{pinax-project-}}}.