Любое простое приложение взаимодействует с внешним миром: использует базу данных, обращается к внешним сервисам, например, платежным, отправляет письма и получает список друзей. Для большинства этих операций необходимы специальные параметры: ключи, пароли, адреса серверов и порты. Они называются конфигурацией приложения.
В этом уроке разберем, где хранить конфигурацию.
Приложение двенадцати факторов
Самый простой и неправильный выбор — хранить конфигурацию прямо в приложении. У такого подхода две проблемы:
- Часть этих данных секретная. Хранить их в репозитории нельзя из-за возможных проблем с безопасностью. Любой, у кого есть доступ к репозиторию, сможет получить доступ. Есть вариант с шифрованием, но он выходит за рамки обсуждаемой темы. Для интересующихся рекомендуем изучить Ansible Vault
- При изменении этих параметров придется заново выкладывать сайт. По сути, ничего не изменилось: нет новых фич, нет исправления старых багов. Просто изменилась конфигурация
В 2011 году разработчики компании Heroku выложили в интернете сайт, который называется 12factors. Он описывает методологию для создания веб-приложений. Она уменьшает затраты на установку и настройку приложения, повышает переносимость между средами исполнения, позволяет масштабироваться без существенных изменений в инструментах, архитектуре и практике разработки. С тех пор эта методология фактически стала стандартом в индустрии.
Рекомендуем полностью изучить этот документ. Сейчас же нас интересует один его аспект — конфигурация. Двенадцать факторов требуют строгого разделения конфигурации и кода. Конфигурация может меняться между развертываниями: локальное окружение разработчика, продакшен, среда для тестирования. Код не меняется.
Конфигурация должна передаваться в приложение снаружи. Единственный универсальный способ сделать это — использовать переменные окружения.
Переменные окружения
У Django большое количество настроек для разных подсистем, которые задаются через файл settings.py. Например, так можно запустить фреймворк в режиме отладки:
# При запуске устанавливается переменная DEBUG со значением True
DEBUG = True
Таких переменных довольно много. Например, они отвечают за настройку кеширования или за отправку почты. Все они указываются в файле settings.py.
Некоторые такие настройки конфиденциальны и должны храниться отдельно от основного кода проекта. Для этих целей используются переменные окружения:
import os
SECRET_KEY = os.environ['SECRET_KEY']
У данного способа есть несколько недостатков:
- Переменные загружаются только из окружения
- Необходимо обрабатывать исключения KeyError
- Необходимо конвертировать типы вручную
Для простоты конфигурации Django есть сторонняя библиотека python-dotenv. Она позволяет загружать переменные не только из окружения, но и из специального файла .env, который находится в корне проекта. Этот файл не хранится в репозитории. Он специфичен для окружения, в котором идет запуск. Вот его пример:
DEBUG=True
SECRET_KEY=your-secret-key
DATABASE_URL=psql://user:user-password@127.0.0.1:8458/database
SQLITE_URL=sqlite:///my-local-sqlite.db
CACHE_URL=memcache://127.0.0.1:11211,127.0.0.1:11212,127.0.0.1:11213
REDIS_URL=rediscache://127.0.0.1:6379/1?client_class=django_redis.client.DefaultClient&password=ungithubbed-secret
Это обычный текстовый файл, в каждой строке которого находится имя переменной и ее значение. python-dotenv автоматически подгружает его, и затем эти переменные используются в коде, если это необходимо.
Чтобы подключить python-dotenv, необходимо в файле settings.py произвести следующие настройки:
from dotenv import load_dotenv # Импортируем environ
load_dotenv() # Загрузка переменных окружения из файла .env
Теперь можно использовать переменные окружения, которые описаны в файле .env:
import os
SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = os.getenv('DEBUG', False)
Для конфигурации продакшен-окружения одной библиотекой не обойтись. Здесь нужно применять либо системы управления конфигурацией, такие как Ansible, либо использовать системы оркестрации, например, Kubernetes, либо системы, подобные Vault.
База данных
По умолчанию Djano создает локальную SQLite базу, но в продакшен среде зачастую требуется другая база с отдельным сервером. Чтобы поменять базу, достаточно указать параметры подключения в переменной DATABASES
файла settings.py.
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
В зависимости от среды (разработка или продакшен) нам может понадобиться и разная база. Локальная для тестирования в разработке и уже полноценная для задеплоенного приложения. В дополнение, указывать все параметры подключения в коде нельзя - это небезопасно, и потому они также передаются через переменную окружения. Для решения этих задач есть сторонняя библиотека dj-database-url:
# settings.py
import dj_database_url
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES["default"].update(db_from_env)
В примере выше, по умолчанию используется локальная SQLite база. При этом, если будет указана база по ссылке DATABASE_URL
, то использоваться будет она.
Так мы можем разделять среду разработки и деплоя.
Ссылку на базу, как и все конфиденциальные переменные мы также храним в .env
.
Самостоятельная работа
- Добавьте библиотеку python-dotenv
- Перенесите основные параметры в файл переменных окружения .env
- Настройте считывание основных параметров в файле settings.py из переменных окружения
Дополнительные материалы

Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.