Changing Django settings at runtime

DjangoRuntimeSettings

Django Problem Overview


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?

  1. Create a model for my settings (this gives me the various types and validation)
  2. 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
  3. 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:

  1. Adding or changing the available settings requires a schema migration (south). - I can live with that.
  2. I have a model with possibly multiple instances but really only need a singleton. - That could actually be a useful feature at some point.
  3. 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.
  4. 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?

Django Solutions


Solution 1 - Django

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:

  • you can bootstrap the settings from the database by using any lower-level database access mechanism to load them; or
  • you can just define your settings in some other model and fetch them directly when you need them.

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.

Solution 2 - Django

Solution 3 - Django

DATABASES is a dict. So you can manipulate how a dictionary:

import django.conf as conf

conf.settings.DATABASES['default']['NAME'] = 'novo_banco'

Solution 4 - Django

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.

Solution 5 - Django

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.

from django.conf import settings

settings._wrapped.INSTALLED_APPS = () ## *really work*

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.

Solution 6 - Django

You can use recomended .configure() method of settings module:

from django.conf import settings
settings.configure(DEBUG=True)

settings module has additional handy features. Check docs.

Solution 7 - Django

You cannot directly modify the settings.py file For example: If u want change the database at runtime, you should Separate the configuration of the database

# Projecr_name/user_database.py
user_database = {
'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'name',
    'USER': 'admin',
    'PASSWORD': '111111',
    'HOST': '127.0.0.1',
    'PORT': '3306'
},
'user_db': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'user1',
    'USER': 'admin',
    'PASSWORD': '22222',
    'HOST': '127.0.0.1',
    'PORT': '3306'
}
}
# Projecr_name/settings.py
from .user_database import user_database
...
DATABASES = user_database
...

Call in your logical view

# view.py
from ../Projecr_name/user_database import user_database
class Some(...):
    def Some(request):
    user_database['user_db']['NAME']='user2'

then you can change any setting at runtime use this way

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanny W. AdairView Question on Stackoverflow
Solution 1 - DjangoAndré CaronView Answer on Stackoverflow
Solution 2 - DjangoChuckView Answer on Stackoverflow
Solution 3 - DjangoarannasousaView Answer on Stackoverflow
Solution 4 - DjangoraphaelwctView Answer on Stackoverflow
Solution 5 - DjangoalexView Answer on Stackoverflow
Solution 6 - DjangoFusionView Answer on Stackoverflow
Solution 7 - DjangoKevinView Answer on Stackoverflow