How we structure our Django web application's configuration settings

November 15, 2019

We have a relatively long-standing Django web application, first written for Django 1.2. That was a long time ago and I didn't really know what I was doing, so when I began the web application I did what Django more or less suggests. I ran 'django-admin startproject' to set up the initial directory structure and files, including the settings.py that contains various configuration settings for the application, and then started editing that generated settings.py to add all of the customizations we needed. This turned out to be a little bit of a mistake.

The problem is that what Django wants you to have in settings.py and how it's been structured has varied over Django versions; the settings.py from Django 1.2 is not what you'd get (and not really what you want) if you re-ran 'django-admin startproject' today. Because I had mingled our local customizations into settings.py, I couldn't just have Django re-generate it and replace our old Django 1.2 version with the new, up to date one that would be set up like Django 1.9 wanted. So when I redid our settings.py for Django 1.9, I restructured how it was set up to put many of our settings into a separate file (or actually a cascade of them).

(I also made a little mistake by accidentally dropping a setting we needed because I hadn't commented it.)

My current approach is that the only things that go in settings.py itself are minimal modifications to Django settings that are already specified there, especially ones that are structured and ordered data, like INSTALLED_APPS, MIDDLEWARE, and TEMPLATES. Our modifications to all of these are commented with explicit markers, so I can find them when I need to propagate them into a new version of settings.py. All of our other settings go into a separate file, ((cslabsettings.py), which is pulled into settings.py in an addition at the end:

# CSLAB:
# This is where our actual settings live.
from app.cslabsettings import *

This has all of our settings for our application, and also some Django settings that aren't set in settings.py and so don't have to be modified there, such as ADMINS (cf). Because we pull this into settings.py, all of the usual Django things just work without special configuration.

We then have a layer or two of additional settings files on top of this. For development, I have a settings_dev.py that imports (settings.py)) and then overrides bits and pieces (for example, to set 'DEBUG=true'). To use it, I have a manage_dev.py which is just the standard manage.py modified to use settings_dev. I also have a settings_wsgi.py, which contains settings that are specific to running under WSGI instead of in management commands, and a settings_wsgi_dev.py that is for the obvious thing.

(Now that I look at settings_wsgi.py, it's possible that it has too many settings and should be trimmed back. The problem with having a whole cascade of settings files is that it's easy to lose track of what is set in what and what still needs to be overridden in the latest one.)

This is much the same idea as my ancient modular approach to Apache configuration, and for the same reason. The Django generated settings.py is pretty much a system supplied file, which means that periodically you want to replace it with a new system supplied version. The less you change in it, the less work you have to do when this happens.

(This entry is the long delayed explanation for the little bit at the end of this entry.)

Written on 15 November 2019.
« TCP/IP and a consequence of reliable delivery guarantees
The operational differences between notifications and logs »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Nov 15 23:55:18 2019
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.