Configuring Django Settings: Best Practices

Mar 26, 2024
/
7 min read
Configuring Django Settings: Best Practices
Alex Ryabtsev
Alex Ryabtsev
Backend Competency & Tech Lead

This article is intended for engineers who use the Django framework. It gives a deep insight and best practices into configuring Django project settings, and the pros and cons of different approaches.

In the article, Django settings.py explained, you will also find recommendations concerning tools, best practices, and architectural solutions, all time-tested and proven by successful projects. And if you still have questions after reading it, you can always leave a comment below or use our contact form. The article is based on Django Stars’ vast experience with real projects. Our Django Developers team is ready to speed up your development project.

Managing Django Settings: Issues

Different environments. Usually, you have several environments: local, dev, ci, qa, staging, production, etc. Each environment can have its own specific settings (for example: DEBUG = True, more verbose logging, additional apps, some mocked data, etc). You need an approach that allows you to keep all these Django setting configurations.
Sensitive data. You have SECRET_KEY in each Django project. On top of this there can be DB passwords and tokens for third-party APIs like Amazon or Twitter. This data cannot be stored in VCS.
Sharing settings between team members. You need a general approach to eliminate human error when working with the settings. For example, a developer may add a third-party app or some API integration and fail to add specific settings. On large (or even mid-size) projects, this can cause real issues.
Django settings are a Python code. This is a curse and a blessing at the same time. It gives you a lot of flexibility, but can also be a problem – instead of key-value pairs, settings.py can have a very tricky logic.

Setting Django Configurations: Different Approaches

There is no built-in universal way to configure Django settings without hardcoding them. But books, open-source and work projects provide a lot of recommendations and approaches on how to do it best. Let’s take a brief look at the most popular ones to examine their weaknesses and strengths.

settings_local.py

This is the oldest method. I used it when I was configuring a Django project on a production server for the first time. I saw a lot of people use it back in the day, and I still see it now.

The basic idea of this method is to extend all environment-specific settings in the settings_local.py file, which is ignored by VCS. Here’s an example:

settings.py file:

settings_local.py file:

Pros:

  • Secrets not in VCS.

Cons:

  • settings_local.py is not in VCS, so you can lose some of your Django environment settings.
  • The Django settings file is a Python code, so settings_local.py can have some non-obvious logic.
  • You need to have settings_local.example (in VCS) to share the default Django configurations for developers.

Separate settings file for each environment

This is an extension of the previous approach. It allows you to keep all configurations in VCS and to share default settings between developers.
In this case, there are multiple files from which projects on Django get settings, and you make a settings package with the following file structure:

settings/
   ├── __init__.py
   ├── base.py
   ├── ci.py
   ├── local.py
   ├── staging.py
   ├── production.py
   └── qa.py

settings/local.py:

To specify for a project you run which Django configuration file to use, you need to set an additional parameter:

Pros:

  • All environments are in VCS.
  • It’s easy to share settings between developers.

Cons:

  • You need to find a way to handle secret passwords and tokens.
  • “Inheritance” of settings can be hard to trace and maintain.

Environment variables

To solve the issue with sensitive data, you can use environment variables in Django.

This is the simplest example using Python os.environ and it has several issues:

  1. You need to handle KeyError exceptions.
  2. You need to convert types manually (see DATABASE_PORT usage).

To fix KeyError, you can write your own custom wrapper. For example:

Also, you can set default values for this wrapper and add type conversion. But actually there is no need to write this wrapper, because you can use a third-party library (we’ll talk about this later).

Pros:

  • Django config is separated from code.
  • Environment parity – you have the same code for all environments.
  • No inheritance in settings, and cleaner and more consistent code.
  • There is a theoretical grounding for using Django environment variables – 12 Factors.

Cons:

  • You need to handle sharing default config between developers.

12 Factors

12 Factors is a collection of recommendations on how to build distributed web-apps that will be easy to deploy and scale in the Cloud. It was created by Heroku, a well-known Cloud hosting provider.
As the name suggests, the collection consists of twelve parts:

  1. Codebase
  2. Dependencies
  3. Config
  4. Backing services
  5. Build, release, run
  6. Processes
  7. Port binding
  8. Concurrency
  9. Disposability
  10. Dev/prod parity
  11. Logs
  12. Admin processes

Each point describes a recommended way to implement a specific aspect of the project. Some of these points are covered by instruments like Django, Python, pip. Some are covered by design patterns or the infrastructure setup. In the context of this article, we are interested in one part: Configuration.

Its main rule is to store configuration in the environment. Following this recommendation will give us strict separation of config from code.
You can read more on 12factor.net.

django-environ

Based on the above, we see that Django env variables are the perfect place to store settings.
Now it’s time to talk about the toolkit.

Writing code using os.environ could be tricky sometimes and require additional effort to handle errors. It’s better to use django-environ instead.

Technically it’s a merge of:

This app gives a well-functioning API for reading values from environment variables or text files, handful type conversion, etc. Let’s look at some examples.
Django settings.py file before:

Settings.py in Django after:

.env file:

Setting Structure

Instead of splitting settings by environments, you can split them by the source: Django, third- party apps (Celery, DRF, etc.), and your custom settings.

File structure:

project/
├── apps/
├── settings/
│   ├── __init__.py
│   ├── djano.py
│   ├── project.py
│   └── third_party.py
└── manage.py

__init__.py file:

Each module could be done as a package, and you can split it more granularly:

project/
├── apps/
├── settings/
│   ├── project
│   │   ├── __init__.py
│   │   ├── custom_module_foo.py
│   │   ├── custom_module_bar.py
│   │   └── custom_module_xyz.py
│   ├── third_party
│   │   ├── __init__.py
│   │   ├── celery.py
│   │   ├── email.py
│   │   └── rest_framework.py
│   ├── __init__.py
│   └── djano.py
└── manage.py

Naming Conventions

Naming of variables is one of the most complex parts of development. So is naming of settings. We can’t imply on Django or third-party applications, but we can follow these simple rules for our custom (project) settings:

  • Give meaningful names to your settings.
  • Always use the prefix with the project name for your custom (project) settings.
  • Write descriptions for your settings in comments.

Bad example:

Good example:

Change MYAWESOMEPROJECT to you real project name.

Django Settings: Best practices

Here are some of the Django production settings best practices:

  • Keep settings in environment variables.
  • Write default values for production configuration (excluding secret keys and tokens).
  • Don’t hardcode sensitive settings, and don’t put them in VCS.
  • Split settings into groups: Django, third-party, project.
  • Follow naming conventions for custom (project) settings.

Read also: Python Rule Engine: Logic Automation & Examples

Conclusion

The Settings file is a small but very important part of any Django project. If you do it wrong, you’ll have a lot of issues during all phases of development. But if you do it right, it will be a good basis for your project that will allow it to grow and scale in the future.

Using the Django settings environment variables approach, you can easily switch from a monolith to microservice architecture, wrap your project in Docker containers, and deploy it in any VPS or Cloud hosting platform such as: Amazon, Google Cloud, or your own Kubernetes cluster.

Properly utilizing Django models methods can significantly enhance your application’s database interactions and data management.

If you are looking for experienced developers for your project, contact the Django Stars team.

Sources:

Frequently Asked Questions
What is the purpose of settings.py?
The settings.py file is typically used to store configuration information in Django. It may contain the site URL, paths to various directories, and other values that the executable code may use. By changing and supplementing this file, the developers configure Django projects.
How to import Django settings
There are various approaches for setting Django configurations. You can add from .settings_local import * to your settings.py file to import settings from settings_local.py. Also, you can make a settings package with different Python files to separate settings and specify for a project you run which Django configuration to use. And you can use environment variables.
How to use django-environ with several settings files?
There's no proper solution for this. Either you need to duplicate setting definition in several files or you need to merge several files into one. (In most cases it happens for DEBUG setting, so just copy/paste it.) Importing from another module can lead to circular cross imports, but it really depends on your project layout.
How to set environment variables in Django?
To set environment variables, you can write code using os.environ. But it could be tricky sometimes and require additional effort to handle errors. Therefore, a convenient alternative is to use django-environ. This Python package gives a well-functioning API for reading values from environment variables or text files, handful type conversion, etc.
Which file has Django default configurations?
Typically, Django default configurations are stored in the settings.py file. However, there are other popular approaches, such as extending environment-specific settings in the settings_local.py file, splitting settings into different files for each environment, or storing settings in environment variables.

Have an idea? Let's discuss!

Contact Us
Rate this article!
6 ratings, average: 3.83 out of 5
Very bad
Very good
Subscribe us

Latest articles right in
your inbox

Thanks for
subscribing.
We've sent a confirmation email to your inbox.

Subscribe to our newsletter

Thanks for joining us! 💚

Your email address *
By clicking “Subscribe” I allow Django Stars process my data for marketing purposes, including sending emails. To learn more about how we use your data, read our Privacy Policy .
We’ll let you know, when we got something for you.