Настройки для продакшена и секреты
Один и тот же settings.py не годится и для разработки, и для прода. Разделение настроек и вынос секретов — первый шаг к боевому развёртыванию.
Суть: секреты (SECRET_KEY, пароли) держат в переменных окружения, а не в коде. Для прода переключают DEBUG=False, заполняют ALLOWED_HOSTS и настраивают реальную базу. Часто разделяют настройки на base/dev/prod.
Почему настройки нужно разделять
В разработке удобно: DEBUG=True, SQLite, подробные ошибки. В продакшене всё наоборот: DEBUG=False, PostgreSQL, скрытые трассировки, HTTPS. Держать оба режима в одном файле с условиями — путаница и риск выкатить отладочный режим на боевой сервер. Поэтому настройки разделяют или параметризуют через окружение.
Секреты — в окружение, не в код
Главное правило безопасности: никаких секретов в git. SECRET_KEY, пароли базы, ключи API читают из переменных окружения. Локально их хранят в файле .env (который добавлен в .gitignore):
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "False") == "True"
ALLOWED_HOSTS = os.environ.get("DJANGO_HOSTS", "").split(",")
Боевая база данных
SQLite хорош для разработки, но в продакшене берут PostgreSQL — он выдерживает параллельные записи и большие объёмы. Настройка тоже через окружение:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ.get("DB_HOST", "localhost"),
"PORT": os.environ.get("DB_PORT", "5432"),
}
}
Как это работает под капотом
Чтение конфигурации из окружения с дефолтами — языко-независимая логика «возьми переменную или подставь значение по умолчанию, приведя к нужному типу». Вот её модель:
# Попробуй сам ▶ — чтение настроек из окружения
fake_env = {
"DJANGO_DEBUG": "False",
"DJANGO_HOSTS": "example.com,www.example.com",
"DB_PORT": "5432",
}
def env(key, default=None, cast=str):
raw = fake_env.get(key, default)
if raw is None:
raise KeyError(f"Не задана обязательная переменная {key}")
if cast is bool:
return str(raw).lower() in ("true", "1", "yes")
if cast is list:
return [x.strip() for x in str(raw).split(",") if x.strip()]
return cast(raw)
DEBUG = env("DJANGO_DEBUG", "False", bool)
HOSTS = env("DJANGO_HOSTS", "", list)
PORT = env("DB_PORT", "5432", int)
print("DEBUG:", DEBUG, type(DEBUG).__name__)
print("HOSTS:", HOSTS)
print("PORT :", PORT, type(PORT).__name__)
Библиотеки вроде django-environ делают то же самое, но с разбором .env-файлов и приведением типов из коробки.
Логирование вместо print
В разработке отладочный вывод делают через print, но в продакшене это бесполезно: вывод теряется, не пишется в файлы и не различает уровни важности. Django использует стандартный модуль logging Python, настраиваемый словарём LOGGING в settings. Вы задаёте обработчики (вывод в файл, в консоль, отправка ошибок на почту), уровни (DEBUG, INFO, WARNING, ERROR) и форматтеры. На проде обычно пишут WARNING и выше в файл или внешний сервис сбора логов, а критические ошибки шлют команде. Грамотно настроенное логирование — это глаза и уши приложения в бою: без него вы узнаёте о проблеме только от рассерженных пользователей. Поэтому логирование настраивают сразу, а не «когда-нибудь потом».
Структура split-settings
Популярный подход — папка settings/ с файлами base.py (общее), dev.py (импортирует base, добавляет отладку) и prod.py (импортирует base, ужесточает безопасность). Какой использовать — выбирает переменная DJANGO_SETTINGS_MODULE.
settings/ ├── base.py ── общие настройки (INSTALLED_APPS, шаблоны) ├── dev.py ── from .base import *; DEBUG=True; SQLite └── prod.py ── from .base import *; DEBUG=False; Postgres; HTTPS
Частые ошибки
- Коммитить SECRET_KEY и пароли в git. Утечка из истории репозитория — частая причина взломов.
- Оставить DEBUG=True на проде. Любая ошибка покажет посетителю трассировку с кодом и настройками.
- Пустой ALLOWED_HOSTS при DEBUG=False. Сайт вернёт ошибку на все запросы.
- Использовать SQLite в продакшене под нагрузкой. Блокировки при параллельной записи.
Best practices
- Все секреты — через переменные окружения;
.envв.gitignore. - Разделяйте настройки на base/dev/prod или параметризуйте через окружение.
- В продакшене: PostgreSQL,
DEBUG=False, заполненныйALLOWED_HOSTS. - Сгенерируйте новый
SECRET_KEYдля прода, не используйте дефолтный из шаблона.
Итоги
Настройки для разработки и прода разные. Секреты живут в окружении, не в коде. Прод требует DEBUG=False, заполненного ALLOWED_HOSTS и боевой базы PostgreSQL. Разделение на base/dev/prod наводит порядок. Теперь развернём приложение на боевом сервере.