Переменные окружения в Django: пошаговая настройка
Как вынести SECRET_KEY, пароль базы и режим отладки из settings.py в переменные окружения — от установки библиотеки до проверки, что всё читается. Займёт около 20 минут.

К концу этой инструкции у вас будет проект Django, где секретный ключ, пароль базы данных и флаг DEBUG хранятся отдельно от кода — в файле .env, который не попадает в git. Локально они читаются из этого файла, на сервере — из настоящих переменных окружения. Настройка занимает около 20 минут, если Django уже установлен.
Проверено на Django 5.x и Python 3.11+. Библиотека python-dotenv — версии 1.x. С более старыми версиями Django (3.x, 4.x) подход работает так же: он не зависит от внутренностей фреймворка.
Что нужно иметь до начала
- Готовый проект Django с файлом
settings.py(обычно внутри пакета видаmyproject/settings.py). - Активированное виртуальное окружение — то самое, где установлен Django. Устанавливать библиотеку нужно именно в него, иначе Django её не увидит.
- Инициализированный репозиторий git — не обязательно, но иначе смысл выносить секреты частично теряется.
- Доступ к терминалу в корне проекта (там, где лежит
manage.py).
Шаг 1. Установите библиотеку для чтения .env
Django сам не умеет читать файлы .env — нужна отдельная библиотека. Самый распространённый вариант — python-dotenv:
pip install python-dotenvПроверка: выполните pip show python-dotenv. Должен вывестись блок с полем Version: 1.x.x. Если команда пишет WARNING: Package(s) not found — вы установили библиотеку не в то окружение, вернитесь и активируйте нужное.
Альтернатива
Есть библиотека django-environ — она умеет разбирать URL базы данных и типизировать значения. Здесь берём python-dotenv, потому что она минимальна и не привязана к Django. Если позже понадобится парсить DATABASE_URL одной строкой — django-environ будет удобнее, это отдельная тема.
Шаг 2. Создайте файл .env в корне проекта
Рядом с manage.py создайте файл с именем .env (точка в начале, без расширения). Пример содержимого:
DJANGO_SECRET_KEY=zamените-на-свой-длинный-случайный-ключ
DJANGO_DEBUG=True
DATABASE_NAME=mydb
DATABASE_USER=myuser
DATABASE_PASSWORD=YOUR_DB_PASSWORD
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432Формат простой: ИМЯ=значение, по одному на строку, без пробелов вокруг знака равенства и без кавычек (кавычки станут частью значения). Значение всегда читается как строка — про приведение типов ниже.
Проверка: файл существует и в нём нет пустых значений вроде DATABASE_PASSWORD=. Пустая строка — это валидное значение, а не «взять по умолчанию».
Шаг 3. Добавьте .env в .gitignore
Смысл всей затеи — не хранить секреты в репозитории. Откройте (или создайте) файл .gitignore в корне и добавьте строку:
.envПроверка: выполните git status. Файла .env не должно быть ни в изменениях, ни в неотслеживаемых файлах. Если он всё ещё виден и вы его раньше коммитили — git продолжает его отслеживать; уберите из индекса командой git rm --cached .env и закоммитьте это изменение.
Если .env хоть раз попал в коммит — считайте, что секреты из него скомпрометированы. Их нужно перевыпустить, а не просто удалить файл: история git хранит старую версию.Шаг 4. Подключите чтение .env в settings.py
В самом верху settings.py, до первого обращения к переменным, добавьте загрузку файла:
import os
from pathlib import Path
from dotenv import load_dotenv
BASE_DIR = Path(__file__).resolve().parent.parent
# Читаем .env из корня проекта
load_dotenv(BASE_DIR / ".env")load_dotenv кладёт значения из файла в os.environ. По умолчанию она не перезаписывает переменные, которые уже заданы в окружении, — это правильно: на сервере настоящие переменные должны иметь приоритет над файлом.
Проверка: запустите python manage.py shell и выполните import os; print(os.environ.get("DATABASE_NAME")). Должно вывестись значение из .env, а не None.
Шаг 5. Замените жёстко прописанные значения
Теперь замените константы в settings.py на чтение из окружения.
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
# os.environ всегда возвращает строку, поэтому сравниваем явно
DEBUG = os.environ.get("DJANGO_DEBUG", "False") == "True"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DATABASE_NAME"],
"USER": os.environ["DATABASE_USER"],
"PASSWORD": os.environ["DATABASE_PASSWORD"],
"HOST": os.environ.get("DATABASE_HOST", "127.0.0.1"),
"PORT": os.environ.get("DATABASE_PORT", "5432"),
}
}Два разных обращения здесь не случайны:
os.environ["..."]— квадратные скобки, падает с ошибкой, если переменной нет. Так стоит читать всё, без чего проект не должен запускаться: секретный ключ, имя базы, пароль.os.environ.get("...", "значение")— возвращает запасное значение, если переменной нет. Годится для настроек с разумным умолчанием: хост, порт.
Проверка: запустите python manage.py runserver. Сервер должен подняться без ошибок. Если упал на KeyError — одной из обязательных переменных нет в .env или имя написано по-разному в файле и в коде.
Про булевы значения и приведение типов
Главная ловушка новичка — считать, что DEBUG=True в .env станет питоновским True. Не станет. Значение придёт строкой "True", а непустая строка в булевом контексте всегда истинна — включая строку "False". Поэтому в примере выше стоит явное сравнение == "True". То же касается чисел: порт придёт строкой "5432"; если код где-то ждёт int, оберните в int(...).
Если не получилось
KeyError: 'DJANGO_SECRET_KEY'— переменной нет в окружении. Проверьте, что.envлежит именно там, куда указываетload_dotenv(в примере — рядом сmanage.py), и что имя в файле совпадает с ключом в коде до буквы.ModuleNotFoundError: No module named 'dotenv'— библиотека установлена не в то окружение. Активируйте нужное и повторитеpip install python-dotenv. Обратите внимание: пакет ставится какpython-dotenv, а импортируется какdotenv.- Значения читаются со старыми данными — вы поменяли
.env, но сервер не перечитал файл.load_dotenvотрабатывает один раз при старте; после правки.envперезапуститеrunserver. DEBUGостаётсяTrue, хотя в .env стоитFalse— скорее всего значение читается без сравнения со строкой (простоDEBUG = os.environ.get("DJANGO_DEBUG")). Непустая строка истинна, вернитесь к явному== "True".- Файл читается, но переменные пустые — проверьте, нет ли в
.envпробелов вокруг знака=или обрамляющих кавычек: они попадают в значение.
Как устроено окружение на сервере
На проде файла .env обычно нет — переменные задаются средой запуска. Логика при этом не меняется: load_dotenv не найдёт файл, тихо ничего не сделает, а os.environ прочитает настоящие переменные. Где их задавать, зависит от того, как запущен проект:
| Способ запуска | Где задать переменные |
|---|---|
| systemd-сервис | директивы Environment= или файл через EnvironmentFile= в юните |
| Docker | секция environment или env_file в compose, флаг -e у docker run |
| Панель хостинга / PaaS | раздел настроек окружения в интерфейсе |
Точный синтаксис директив systemd и ключей compose сверяйте с их документацией — он не относится к Django и меняется независимо.
Что делать дальше
Сгенерируйте новый SECRET_KEY для прода, а не переносите ключ из шаблона проекта: старый мог утечь через историю git. Создайте отдельный файл .env.example с пустыми значениями и закоммитьте его — по нему коллеги поймут, какие переменные нужны, не видя ваших секретов. И проверьте, что на сервере DEBUG действительно приходит выключенным: DEBUG=True в проде отдаёт трассировки со всеми настройками случайному посетителю.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: python-dotenv — официальная документация (PyPI), Django settings — официальная документация
Частые вопросы
У меня Django 4.2, а не 5.x. Подход подойдёт?
Сервер не видит переменные из .env, хотя локально всё работает. Почему?
Чем python-dotenv отличается от django-environ?
Обязательно ли называть файл именно .env?
Я случайно закоммитил .env с паролями. Достаточно удалить файл и добавить в .gitignore?
Почему DEBUG остаётся включённым, хотя в .env я написал False?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.