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-}}}.