So it's time to put your code into production. That means you have to connect some third party stuff, probably some external database or SMTP server. At the same time it would be nice to keep an option to modify and test your codebase with your local database and double-check on some other staging or QA server. But how to achieve this with default
Searching for the solution I found several approaches of splitting the Django settings, but one that worked for me appeared to be a mixture. Here's how I've got it to work with AWS EC2, but it should work with any python environment where you can set your own env variables.
- Django settings as a module.
- Key environmental variables for production and/or staging servers.
your_main_django_app -settings --__init__.py --base.py --local.py --production.py --staging.py -__init__.py -asgi.py -urls.py -views.py -wsgi.py
1. Set environmental variable with unique key or use one.
I didn't set any env vars during development. But once I deployed my app to the staging server, it got a new env variable called
'RDS_DB_NAME'. I used it to differentiate between my local server and staging/production, but you can use your own unique key to perform the main check in the
__init__.py file (i.e.
'ENV_NAME' : 'Staging').
2. Prepare base.py
from pathlib import Path import os # The most important thing is to be build relative path BASE_DIR = Path(__file__).resolve().parent.parent.parent INSTALLED_APPS =  #...other environmentally independent settings # (TEMPLATES, WSGI_APPLICATION, TIME_ZONE, STATIC_ROOT etc.)
3. Add environment-specific settings
Since we have base.py, we can put the rest of the settings into their respective files:
production.py (you've got the idea).
By the way, don't forget to place your sensitive data (secrets, api keys etc.) into env variables instead of hard-coding them into your
production.py. Here's the example of retrieving them in your settings:
4. Tweak the import in init.py with if statement
Having all the settings in a separate module allows us not to specify local config directly each time we run
manage.py runserver, because Django loads settings.py by default. And our settings module/folder is simply an equivalent to it.
Here's the init.py from the settings folder.
from .base import * import os if os.environ.get("ENV_NAME") == 'Production': from .production import * elif os.environ.get("ENV_NAME") == 'Staging': from .staging import * else: from .local import *
Now, whenever your Django app is initialized on the server, your environment variable called
"ENV_NAME" will determine the proper settings file. And if it's just your local dev server, no env variables will be accessible and your app will fall back to
*If you happened to use AWS Beanstalk for deploying python app, you might want to simplify your
__init__.py to something shorter:
from .base import * import os if os.environ.get("RDS_DB_NAME") is None: from .local import *
In this case, we're only telling the server to check one env variable and fallback to local.py. What about the production configuration then? Well, Beanstalk allows you to specify preferred settings in an environmental variable called
DJANGO_SETTINGS_MODULE. Thus, you can just tune your Beanstalk app to load respective configuration like this:
And that's all.
Everyone gets its own settings and your
manage.py runserver works as before. Happy production.
This article was originally published in my blog post.