Usually, it’s a good idea to avoid multiple configuration files, instead, keep your project setup simple. But that’s
not always possible, as a Django project starts to grow, the settings.py
module can get fairly complex. In those
cases, you also want to avoid using if
statements like if not DEBUG: # do something...
. For clarity and strict
separation of what is development configuration and what is production configuration, you can break down
the settings.py
module into multiple files.
Basic Structure
A brand new Django project looks like this:
First thing we want to do is to create a folder named settings
, rename the settings.py
file to base.py
and
move it inside the newly created settings
folder. Make sure you also add a __init__.py
in case you are working with
Python 2.x.
As the name suggests, the base.py
will provide the common settings among all environments (development, production, staging, etc).
Next step now is to create a settings
module for each environment. Common use cases are:
- ci.py
- development.py
- production.py
- staging.py
The file structure would look like this:
Configuring a New Settings.py
First, take as example the following base.py
module:
settings/base.py
There are a few default settings missing, which I removed so the example doesn’t get too big.
Now, to create a development.py
module that “extends” our base.py
settings module, we can achieve it like this:
settings/development.py
And a production.py
module could be defined like this:
settings/production.py
Two important things to note: avoid using star imports (import *
). This is one of the few exceptions. Star imports
may put lots of unecessary stuff in the namespace which in some cases can cause issues. Another important thing, even
though we are using different files for development and production, you still have to protect sensitive data! Make sure
you keep passwords and secret keys in environment variables or use a library like Python-Decouple which I highly
recommend!
How to Use It
Since we no longer have a settings.py
in the project root, running commands like python manage.py runserver
will
no longer work. Instead, you have to pass which settings.py
module you want to use in the command line:
Or
The next step is optional, but since we use manage.py
often during the development process, you can edit it to set
the default settings module to your development.py
module.
To do that, simply edit the manage.py
file, like this:
manage.py
So, basically we changed the line from:
To:
Now you can run the manage.py
commands again without using the --settings
argument. But remember to refer to the
correct settings module in production!
Some Things You Can Do
Since now we have different settings modules, one thing you can do is removing the AUTH_PASSWORD_VALIDATORS
from the
settings/base.py
and only add it to settings/production.py
module. This way you use simple passwords like “123”
during development but in the production environment it will be protected by the validators.
In your settings/tests.py
or settings/ci.py
you can override the following configuration so your tests run faster:
Conclusions
I hope you found this post useful somehow! Remember to use it carefully!
If you have any questions, please post in the comments below!