Упрощенный пример - имею такую структуру приложения:
config/ # Все конфиги проекта хранятся в одной отдельной директории.
├── __init__.py
└── settings/ # Все настройки
├── __init__.py # Пустой
├── base.py # содержит настройки общие для development и production и указывает на конфиги *.tomlimport dynaconf
...
# BASE SETTINGS
# -----------------------------------------------------------------------------
SETTING_0 = 'value1'
SETTING_1 = 'value2'
...
# DYNACONF
# -----------------------------------------------------------------------------
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of base.py)
# Read more at https://www.dynaconf.com/
settings = dynaconf.Dynaconf(
__name__,
# Эта переменная будет указывать какие настройки использовать(prod/dev).
ENV_SWITCHER_FOR_DYNACONF='EXAMPLE_PROJECT_ENV',
settings_files=['development.toml', 'production.toml'],
)
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
├── development.toml # Настройки для dev среды.
...
DATABASES__default__ENGINE = 'sqlite3'
DATABASES__default__NAME = '@format {this.PROJECT_ROOT_DIR}/db.sqlite3'
...
└── production.toml # Настройки для прода, аналогичны `development.toml`.
main.py
Теперь в приложении я могу:
...
# Указать путь к настройкам:
os.environ.setdefault('PROJECT_SETTINGS_MODULE', 'config.settings.base') # `config.settings.base` выглядит гораздо менее логично чем `config.settings`.
# Использовать переменную окружения для выбора конфигурации:
os.environ.setdefault('EXAMPLE_PROJECT_ENV', 'production')
...
Проблема: Для указания пакета настроек я использую путь `config.settings.base`, хотя
base позволяет получить доступ к dev/prod настройкам, а не только базовым - имя `base` в данном случае не соответствует назначению объекта, к тому-же base.py вроде-как должен хранить только настройки,
а он еще и содержит логику с указанием пути к остальным конфигам -
на мой взгляд это нарушение SRP.
Решение: импорт всего содержимого `base.py` в `settings/__init__.py`, заодно перенеся всю логику загрузки конфигов, тем самым оставив в `base.py` только базовые настройки.
config/
├── __init__.py
└── settings/
├── __init__.py # Теперь все настройки получаются отсюда.
from .base import *
import dynaconf
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of other
# settings).
# Read more at https://www.dynaconf.com/
settings = dynaconf.Dynaconf(
__name__,
ENV_SWITCHER_FOR_DYNACONF='EXAMPLE_PROJECT_ENV',
settings_files=['development.toml', 'production.toml'],
)
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
├── base.py # теперь содержит только настройки общие для development/production и минимум логики.
...
# BASE SETTINGS
# -----------------------------------------------------------------------------
SETTING_0 = 'value1'
SETTING_1 = 'value2'
...
├── development.toml
└── production.toml
main.py
Преимущества:
Недостатки:
- Наличие логики в __init__.py
Вопрос: является ли логика в __init__.py - плохой практикой? Для меня вот не очень привычно что там что-то лежит. Кто-то говорит, что это нормально, кто-то что это
зло.