Yawd website

oct09

How to keep your django project settings organized

I like to keep my code organized. One of the issues I came across when exploring django coding is the 'settings mess'. Django settings are loaded on a project -and not application- basis. Having a single python module to define settings for a ton of applications is at least frustrating. When looking for a solution to this problem I found this blog post which cleared my head.

Now I always use the inject_app_defaults function in all my yawd projects to allow for application settings as follows:

An example django project treeFigure 1. An example project tree

Consider the above project tree. The project 'MyProject' contains a single application, named 'myapp'. Inside the __init__.py project module I always put the inject_app_defaults code. This function accepts an application name as argument, attempts to load the application's local settings module and injects the settings defined in this (local) module to the project's global settings. Therefore, the project's __init__.py module looks like this:

MyProject/__init__.py
def inject_app_defaults(application):
    """Inject an application's default settings"""
    try:
        __import__('%s.settings' % application)
        import sys
        
        # Import our defaults, project defaults, and project settings
        _app_settings = sys.modules['%s.settings' % application]
        _def_settings = sys.modules['django.conf.global_settings']
        _settings = sys.modules['django.conf'].settings

        # Add the values from the application.settings module
        for _k in dir(_app_settings):
            if _k.isupper():
                # Add the value to the default settings module
                setattr(_def_settings, _k, getattr(_app_settings, _k))
                
                # Add the value to the settings, if not already present
                if not hasattr(_settings, _k):
                    setattr(_settings, _k, getattr(_app_settings, _k))
    except ImportError:
        # Silently skip failing settings modules
        pass

To take advantage of the above snippet, we should first define a settings.py module inside our 'myapp' application, as shown in Figure 1.

myapp/settings.py
from django.conf import settings

MY_APP_SETTING = getattr(settings, 'MY_APP_SETTING', 'Hello settings...')
MY_APP_SETTING_2 = getattr(settings, 'MY_APP_SETTING_2', '..local settings!')

The getattr method allows for overriding your local application settings in the main project settings module. Finally, to make it work we just need to call the inject_app_defaults and inject the settings to the project's global settings. For this to happen automatically as soon as the application is loaded we place the following inside the application's __init__ module:

myapp/__init__.py
from MyProject import inject_app_defaults

inject_app_defaults(__name__)

Everything should be in place by now. All you need to do is access your setting the usual way:

from django.conf import settings

print settings.MY_APP_SETTING

Meta

Published: Oct. 9, 2011
Comments:  
Word Count: 550
Comments powered by Disqus