views:

257

answers:

5

In Django, settings are stored in a file, settings.py. This file is part of the code, and goes into the repository. It is only the developers who deal with this file. The admin deals with the models, the data in the database. This is the data that the non-development staff edits, and the site visitors see rendered in templates.

The thing is, our site, and many others, have lots of settings options that should be edited by non-developer staff. We're talking about stand-alone site-wide constants that really have no place in the database. Putting them in the database will result in numerous pointless queries. Caching could alleviate that, but that seems unnecessarily complex to handle what can be done with a single line in the settings.py file.

I did notice this dbsettings app, but it is old and unmaintained. I also noticed that the django e-commerce app, Satchmo, includes a use-case specific fork of this dbsettings app. We could build something similar into our site, an app that stores some settings as key/value pairs in a single database table, but it just really seems like the wrong approach. Why put something in the DB that doesn't belong there just to make it more easily editable by non-developers?

We have a list of site-wide settings on our Django site that we want to be editable by non-developer administrators. What is the best way of going about this?

+2  A: 

How about putting a sitesettings.py (or whatever) somewhere that your admins can access, then in settings.py do

from sitesettings import *

That seems good and simple, but I may have misunderstood or oversimplified your problem :)

Aaron Lockey
This solution also doesn't work because only tech people can edit files on the server and/or restart the apache.
Apreche
+4  A: 

Something like dbsettings (as you mentioned) seems like the way to go. From the reasons for existence for that project:

Not all settings belong in settings.py, as it has some particular limitations:

  • Settings are project-wide. This not only requires apps to clutter up settings.py, but also increases the chances of naming conflicts.

  • Settings are constant throughout an instance of Django. They cannot be changed without restarting the application.

  • Settings require a programmer in order to be changed. This is true even if the setting has no functional impact on anything else.

If dbsettings doesn't work for you, then implement your own, or fork it. It doesn't seem like it'd be too arduous.

Dominic Rodger
+4  A: 

I'm actually a big fan of dbsettings, and keep meaning to publish my fork that patches it to work with Django 1.1 (not actually a big change). Looks like someone has updated it already.

However, you're probably right that this is overkill for what you need. One thing I've done before is to add a line to the end of settings.py that imports and parses a YAML file. YAML is a simple markup language, which at its most basic is just KEY: VALUE ...

CONSTANT1: MyValue
CONSTANT2: Anothervalue

If you put this somewhere editors can access it, then at the end of settings.py you just do:

import yaml
try:
    globals().update(yaml.load(open('/path/to/my/yaml/file.yml')))
except:
    pass

You'll need the Python YAML library to parse the YML file.

The downside to this approach is that you'll need to restart Apache to get it to pick up the changes.

Edited to add It wouldn't be particularly difficult to build a front end which could edit this file, and provide a button which runs a script to restart Apache.

Daniel Roseman
This solution doesn't work because only tech people can edit files on the server and/or restart the apache.
Apreche
It wouldn't be particularly difficult to build a front end which could edit this file, and provide a button which runs a script to restart Apache.
Daniel Roseman
@Daniel - though at that point you're getting into the same kind of work-level that dbsettings requires.
Dominic Rodger
+1  A: 

If you must avoid server restarts then a logical place for the settings is the database as Dominic and Daniel said, but you'll need to invalidate cached settings object every time it is updated.

Looks like it's possible to re-set values in the cache with Django's low level cache API. All you want should be achievable with these calls:

 cache.set('settings', local_settings)
 cache.add('settings', local_settings)
 local_settings = cache.get('settings')
 cache.delete('settings')
Evgeny
A: 

What about this:

1: Write a simple KeyValue model with a key and a value.

2: Write a function, that imports settings and iterates over all KeyValue objects and add or replace those in settings

3: call that function at the end of settings/urls/cronjob/view...

of course, quite fancy KeyValue models are thinkable, like conditional behaviour (developent/production server)

vikingosegundo