Setting the 'django_settings_module' value

Hi there,

I was just wondering if anyone can clarify the best / most common way of setting the ‘django_settings_module’ setting when deploying to different environments (e.g. Heroku).

Context

I’ve set up my project with separate ‘settings’ files for different environments. Looking at various tutorials, it seems like the simplest way of doing this was to add a ‘settings’ module to my project folder. I’ve then got a ‘base.py’ file containing all common settings, then separate settings files per environment that each import the base settings. All pretty standard. Nothing special.

My structure now looks like this:

django_project/
    settings/
        - __init__.py
        - base.py
        - development.py
        - production.py
        - testing.py
    - __init__.py
    - asgi.py
    - urls.py
    - wsgi.py

Problem

The thing is I’m not quite sure how to set the ‘django_settings_module’ path in my wsgi.py and manage.py files depending on which environment I’m deploying to. At the moment they look like this:

wsgi.py:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_project.settings.development')

manage.py:

def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_project.settings.development')

Obviously I could manually type in this value myself just before deploying to each new environment (e.g. changing ‘development’ to ‘production’ just before deploying to Heroku). However that doesn’t feel right. Surely there’s a more robust and repeatable process than that?

Many thanks in advance for your help.

All the best,

2 Likes

os.environ.setdefault is trying to a default value in your application’s environment variables if one does not already exist.

Since you’re using Heroku, you should be able to go to your Settings page of your app and change the Config variables (see the screenshot below). Heroku will expose any variables defined here as an environment variable to your environment. So, if you want to use your production settings in your Heroku deployment, then you’d add a config variable with a name of DJANGO_SETTINGS_MODULE and, in your case, a value of django_project.settings.production.

I hope that helps!

1 Like

Hi Matt,

Thanks so much for your reply (and thanks for your videos on YouTube – they’ve been really useful to get an idea of how to work with this stuff).

I just wanted to replay this back to make sure I’ve understood how I should work…

When working locally:
I manually switch os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_project.settings.environment') to whatever I need it to be.

For example
django_project.settings.development

Or
django_project.settings.testing

For any environments hosted on Heroku:
I set the config variables in each environment (e.g. staging or production) to what I need it to be. For example the key equals DJANGO_SETTINGS_MODULE and value equals django_project.settings.staging.

Thanks again,

I’d say you’re half right. You’re correct about the Heroku settings side.

Ideally, you should never have to change those Python files. They read from the OS environment variables so, if you set those environment variables, you should be good to go.

Practically, that means you’d set the DJANGO_SETTINGS_MODULE environment variable in your local shell before you start up a local Django web server. For the sake of discussion, let’s assume you’re using ./manage.py runserver for local development.

On a Linux/macOS terminal, you could do something like:

$ export DJANGO_SETTINGS_MODULE=django_project.settings.development
$ ./manage.py runserver

Since you’re using Heroku, you could also use the Heroku toolbelt to handle this as well. I assume you already have a Procfile for Heroku deployments. The heroku local command can run your Procfile commands on your local environment. If you want that command to use the equivalent of config variables on your local machine, then create a file called .env (notice the leading dot) and add a line like:

DJANGO_SETTINGS_MODULE=django_project.settings.development

The heroku local command will read that file, load the values as configuration variables, and start processes on your machine that match with what’s in your Procfile.

Does that make sense?

1 Like

Thanks for that (and sorry for the slow reply – with this lockdown it’s so hard to carve out the time to learn coding!)

Yes that makes perfect sense. I already have a .env file for things like SECRET_KEY, so I’ll put the DJANGO_SETTINGS_MODULE in there. I assume that will override the os.environ.setdefault as it’s a default.

I think I’m beginning to see how it’s possible to use the config variables as a sort of master switch. By changing a single value (e.g. ENVIRONMENT="production") it can point Django to a different .env.production file which has its own values (e.g. a production S3 bucket url).

Thanks again! I’ve definitely got enough now to start experimenting with this setup.

1 Like