Home > Projects > Pitfalls in Django settings

Pitfalls in Django settings

Here are some common pitfalls to avoid when working with Django settings in large projects:

Pitfall #1. One Settings File for All Environments

Your Production server will have different settings from your local development, your QA box, and your team-mate’s local development. You could try to stuff every possibility into one settings file and switch based on environment variables, domain name, or other magical means. However, pretty soon this will become unmanageable. If your settings file has “if/then” statements, then you’re probably doing this.

Instead, you should break out multiple settings files for your various environments. A good practice is to have a “base” or “default” settings file. Put all the settings in here that MUST be present to tie all your Django apps together. Do NOT put security-related information in here. Do NOT put debug-related settings in here.

Because Django is python, you can go one step better in your file organization: Create a “settings” folder, with a “__init__.py” in it. Place all your various settings files here. Then, when you want to switch from the command-line, you can run this command:

$ python manage.py runserver --settings=settings.someconfig

Pitfall #2. Putting PRODUCTION settings in the default settings file.

You want to test your Django project with settings that will actually work on Production, right? Yes, or at least reasonably close. The temptation is to make your settings.py include all the Production settings, and then override them when you’re in development.

This is a great idea…until you get a new developer who checks out the code, then runs syncdb–and repopulates all your tables with the initial data fixtures…ON YOUR PRODUCTION DATABASE!

Rather, your base settings file should not contain any Production values. Instead, it should either contain values that will work for a local developer, or it should be missing these values entirely, so that the developer is forced to specify them.

Pitfall #3. Optionally including a “local” development settings file.

I’ve seen this in a number of projects. There is a “base_settings.py” file, which is good. But to allow the developer to specify alternate settings easily, I see a “settings.py” file that contains this code:

from base_settings import *
try:
    from local_settings import *
except:
    pass

There are two problems with this approach.

First, while this works when the local_settings.py file is valid, it FAILS SILENTLY when there is a bug in the local_settings.py file. And if your base_settings.py file contains security information for Production, you could accidentally be connected to a Production database while developing. (Can anyone say, “Wow! I just destroyed my production data!”)

The second problem with this approach is that it does not allow local_settings.py to override any of the values present in base_settings.py. Rather, local_settings.py can only REDEFINE these settings, because local_settings.py does not ever actually IMPORT them from base_settings.py In short, you can’t do this:

DATABASES['default']['NAME'] = 'my_dev_database'

If you try that, Python will complain than DATABASES is not defined. But…since the Exception is caught and ignored, you don’t know that it’s not working!

A Suggested Best-Practice for Django Settings Files

After falling into these pits multiple times, I’ve come up with this methodology for handling settings files. You’re welcome to use it, too. 🙂

  1. Don’t store a settings.py file in your Source Code Control. This will force the local developer to either symlink (or copy on Windows) the relevant settings file to “settings.py”. Django will complain about a missing settings.py file–even if you use the “–settings” command-line option. Symlinking makes it super-easy to switch out one set of settings during development.
  2. Separate out settings for base, production, QA, and local development. If you can, put them into a dedicated “settings” module, with __init__.py file. NOTE: Some server admins won’t want you storing production settings in your Source Code Control System. That’s OK. Just tell them where the base is, and have them override it in a settings file they keep somewhere else.
  3. Import base settings into the other settings files. This allows you to override base settings, rather than having to redefine them.
  4. BONUS: If you have to rely on system environment variables, domain names, or any other magic, then you should validate the values. Complain mightily about missing values!

Happy Django development! 🙂

  1. No comments yet.
  1. No trackbacks yet.

Leave a comment