I'd like to expose some (app-specific) settings to the admin interface, so users can change them comfortably and also not have to restart Django.
How should I go about this?
I checked out the applications on http://djangopackages.com/grids/g/live-setting/ (btw django-constance was the most appealing) but really what all these apps are doing is storing values in a database, providing a web interface to change them, and caching. Aren't the first two features already built into Django?
The biggest drawbacks I see are that none of the apps are drop-in replacements for the old location of these settings (settings.py), and require me to migrate to their notation, and often add another context processor to access them in templates.
Couldn't I just do this?
- Create a model for my settings (this gives me the various types and validation)
- Instantiate one such object to hold my settings (this allows the users to edit them in the admin interface) - I could dump defaults as fixtures like for other models
- Wrap settings.py so it makes a database query for my settings - http://www.loose-bits.com/2011/04/extending-django-settings-with-derived.html
From my current, naive point of view the only drawbacks I see would be:
- Adding or changing the available settings requires a schema migration (south). - I can live with that.
- I have a model with possibly multiple instances but really only need a singleton. - That could actually be a useful feature at some point.
- Performance/Caching: Looking at http://code.djangoproject.com/svn/django/trunk/django/conf/ I'd have to put a little bit of cleverness into the settings wrapper and/or model, so that model changes clear or update cached values. - doesn't seem to be rocket science.
- Doing the same in another project would require a similar effort again. - I think a single dictionary constant in settings.py, holding model name(s) and field names for the lookups is all that would differ.
Wouldn't this be the best of both worlds - runtime admin (with all its perks), database backend, caching, and none of my settings.USED_TO_BE_IN_SETTINGS_DOT_PY would need any changing. Am I missing something?
DATABASES
is a dict. So you can manipulate how a dictionary:From Django 1.8 docs:
AFAIK, the Django settings are supposed to be immutable. There are multiple reasons for this, the most obvious being that Django is not aware of the server's execution model (prefork / multi-threaded).
Also, you can't load the settings themselves from a Django model because the settings need to be loaded before you can use anything in the ORM.
So, basically, you have two solutions:
The first is an incredible hack and I don't suggest it. The second is much more direct and cleaner, but requires you to change your usual habits (
from django.conf import settings
).The second approach is probably what's implemented by the 3rd-party apps you linked to.
You can use recomended
.configure()
method ofsettings
module:settings
module has additional handy features. Check docs.Honestly I get more Django when I analyze his code. In version 1.4.5 did it (following the module below):
myproject\manage.py
django\core\management__init__.py ## method - execute_manager
django\conf__init__.py ## class - LazySettings; attr - _wrapped
django\utils\functional.py ## class LazyObject; important method - new_method_proxy
Functional option, but it has its risks. In the python "_" considers the attribute as protected.
In the following project: https://github.com/alexsilva/DJPlugins you can see this variable being modified at runtime. the idea of the project is already working.
Take a look: https://bitbucket.org/bkroeze/django-livesettings *Django-Livesettings is a project split from the
Satchmo Project
_. It provides the ability to configure settings via an admin interface, rather than by editing "settings.py".*Maybe it can be helpful for you.