Default settings in Django
A problem with Django is that you can't have default settings unless you're a core Django developer.
This would be nice to have per-app or even per-funky-module, so I decided I'd implement something to support it!
Here's how I did it: create a base class, with a metaclass. When this base class is subclassed, take the attributes and loop through them. If the attribute is all uppercase and isn't set in the main configuration (yet), copy it there.
This ended up looking like:
class GlobalDefaultSettingsBase(type):
def __new__(cls, name, bases, attrs):
from django.conf import settings
new = super(GlobalDefaultSettingsBase, cls).__new__
new_cls = new(cls, name, bases, attrs)
if name == "GlobalDefaultSettings":
return new_cls
for (attr, value) in attrs.iteritems():
if attr == attr.upper() and not hasattr(settings, attr):
print "SETTING", attr, "TO", repr(value)
print settings
print settings._target
setattr(settings, attr, value)
return new_cls
class GlobalDefaultSettings(object):
"""A base class for adding default global settings to the Django settings
object.
All attributes which are in the upper case will be merged into the existing
configuration, unless they're already set.
This is a simple solution for having default settings without `getattr`.
All you have to insure is that your subclass is constructed before the
access of the defaults you provide -- which should be fairly easy.
"""
__metaclass__ = GlobalDefaultSettingsBase
To use it, simply make a subclass and set some settings!
class MyDefaults(DefaultSettings):
MY_SETTING_A = "Hello world!"
MY_SETTING_B = ["Hey guys"]
And that's all you need. If either of the settings is set in the project's settings.py, that setting will effectively take precedence!
Obviously, there's no great place to put this code since it really belongs to core Django.
In fact, Django should itself be using this style - as it is now, all default settings are specified in one huge file without any good correlation.
Comments
