Preamble
This module was born as a result of a rethinking (or misunderstanding) by me of this lengthy document:
Splitting up the settings file , posted on the official Django website.
Formulation of the problem
When you start a web application on Django (both by running the debug server and as a WSGI application), the framework first performs the module that sets the initial settings for the project. The source of the code is set by the environment variable
DJANGO_SETTINGS_MODULE . When creating a Django project in a standard way, for example:
$ django-admin startproject myproject
Creates and settings module. This is the file 'myproject / myproject / settings.py'. Changing and supplementing it, the programmer customizes the project, adds in it its own and third-party components, etc.
In simple projects developed by a single backend programmer, it is quite reasonable to limit oneself to such a settings module. However, as the project grows, the following
Problems:
')
- Project settings for deployment in a combat or test environment are very different from the settings with which the project is launched by the developers. For example, in combat, an application requires a “big” SQL server (PostgreSQL or MySQL) and an additional key-value database for storing cached data (memcached or Redis), while the developer on his computer is used to getting by with SQLite. But the developer settings include additional modules for debugging the project (for example, debug_toolbar), which should not be included in production.
- Variables that set the debug mode in Django ( DEBUG , TEMPLATE_DEBUG, etc.), as well as similar variables for third-party components, should be turned on during development and turned off in production. This is quite a chore to follow when commits.
- The settings module stores sensitive data ( SECRET_KEY , secrets / passwords for authentication of the application on various services, etc.), which are not securely stored in the same repository with the code. This is especially important for open source projects, as well as for large projects in which many developers have access to the code base.
Problems 1 and 2 partially solves the storage in the repository of several configuration files for different occasions and the selection of the desired variable by setting the DJANGO_SETTINGS_MODULE variable. The disadvantage of this solution is that the data in these files are almost completely duplicated. As the project progresses, the developer is obliged to make the same changes in several different configuration files, which is tedious, leads to errors, and so on - in short, contradicts the
DRY principle.
Decision
My
settings module has maximum backward compatibility with the default 'myproject / myproject / settings.py': all links to myproject.settings, if they are really needed, remain valid. At the same time, my solution allows the project administrator to protect private data, and for developers to organize the most comfortable environment for themselves, regardless of colleagues. An additional advantage is the mechanism of inheritance settings: in the local settings, you can access the general settings.
Minus: to store the local settings you need to come up with a separate method, since the repository will not work. The solution to this question usually lies in the organizational plane: transfer the secret from more experienced colleagues to less experienced ones, publish the sample 'local.py' in the private wiki section, etc.
But my method is extremely simple and fast, it does not interfere with the framework for parsing settings by the framework and does not create unnecessary entities like special * .ini / *. Conf-files with parsers, settings classes or modifying function settings.
Hands-on
Here is the sequence of actions for the “upgrade” of the classic settings module (it is assumed that the code is stored in the git-repository):
- Create a 'settings' subdirectory in the main application directory. The path to it will look like this: 'myproject / myproject / settings /'.
- Move your old 'settings.py' to the 'myproject / myproject / settings /' directory created in Section 1 and rename it to 'common.py'. We will refer to this file in the future as “general settings”.
If you use relative paths from the settings file in the project, increase the nesting depth by one directory. For example, a code like:
BASE_DIR = dirname(dirname(abspath(__file__)))
should turn into
BASE_DIR = dirname(dirname(dirname(abspath(__file__))))
- Create the file 'myproject / myproject / settings / local.py'. Immediately add the following code to it:
from myproject.settings.common import *
You can add local settings starting at the next line.
For example, if you are a developer, and want to use the wonderful Django Debug Toolbar tool, you can add the following line:
INSTALLED_APPS += ('debug_toolbar', )
- Create the file 'myproject / myproject / settings / __ init__.py' and enter the following code into it:
try: from myproject.settings.local import * except ImportError: from myproject.settings.common import *
This option is designed for the case when the settings contained in common.py are quite sufficient for the project to start. This is unlikely to be true in a big project. At a minimum, SECRET_KEY should be removed from general settings for security reasons.
If launching a project does not make sense without a local configuration file, you can not try to do with global settings, but throw an exception:
try: from myproject.settings.local import * except ImportError: raise Exception('Please create local.py file')
- Add the file 'myproject / myproject / settings / local.py' to git exceptions. This is the last but not the least important step.
Done! We split the settings file into a common prototype part (common.py), and a local part that inherits the settings from the common one (local.py). Now it's all about the correct decomposition of the settings.