Request for Comments: Auto-Installation of Apps in Django
by Corey Oordt • Published 15 Sep 2009
The problem of pluggable Django apps
Lately we’ve come across a bit of an issue with dependencies. We use pip and virtualenv for our projects and it works great for installing Python dependencies.
However it is not so great if the dependency is a Django pluggable application. There is more you have to do: add all the dependent apps in
INSTALLED_APPS and add the appropriate entry in your base
urls.py. This can be a problem if you aren’t familiar with the app, let alone its dependent apps.
Recently I used pip to test out what I thought was a stand-alone Django pluggable app, only to discover dependency after dependency. This isn’t very pluggable in my book.
Proposal: A method of auto-installing apps
The Django community has developed several patterns that make development easier. Many of them are related to how you configure the
settings.py file for your project. See examples from Usware and this presentation from EuroDjangoCon. I’m proposing a new one, and would like assistance in refining it.
- A pluggable application would contain its own
settings.pyfile containing one or more standard settings:
- In the project’s
settings.pyfile, you would loop through one or more paths containing Django apps/Python packages.
- For each Python package, if it is not already in
INSTALLED_APPS, attempt to import the settings module and see if it has an
- If it does, add it to
INSTALLED_APPSand then check for a
- Add that to a list so you can append/prepend it to your
This system IMHO is:
- Simple to use
- Easily turned off by adding the app to
- Doesn’t interfere with any other packages or functionality
- Easily extensible or customizable
Example code is in a gist at git, but I’ll show it here:
import importlib, os APP_DIRS = (os.path.abspath(os.path.join(PROJECT_ROOT, 'test')),) sys.path.extend(APP_DIRS) BASE_URL_CONFS =  for app_dir in APP_DIRS: for app in os.listdir(app_dir): if not app.startswith('.') and app not in INSTALLED_APPS: try: app_settings = importlib.import_module('%s.settings' % app) if getattr(app_settings, 'APP_NAME', '') != '': print "Auto Installed %s" % app INSTALLED_APPS = INSTALLED_APPS + (app,) base_url_conf = getattr(app_settings, 'BASE_URL_CONF', '') if base_url_conf != '': BASE_URL_CONFS.append(base_url_conf) except ImportError: pass
I’m sure there can be some tweaking to the code, but it gets the idea across. Please feel free to send comments to me at coordt
_at_ washingtontimes.com, or leave a comment down below.