Плюсы:
- Файлы меньше - теперь поддерживать это немного проще
- Разные конфигурации для разработки и деплоя.
Минусы:
- Файлов стало побольше(но это терпимо).
- Все еще нужно редактировать конфиги для изменения настроек.
- Чувствительные данные все еще улетают в vcs.
import environ
env = environ.Env()
READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False)
if READ_DOT_ENV_FILE:
# OS environment variables take precedence over variables from .env
env.read_env(str(ROOT_DIR.path(".env")))
"""Пример фрагмента settings.*.py"""
SECRET_KEY = env.str('SECRET_KEY', default=get_random_secret_key())
DEBUG = env.bool('DEBUG', default=False)
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[])
DATABASES = {'default': env.db('DATABASE_URL')}
STATIC_URL = env.str('STATIC_URL', default='/static/')
EMAIL_HOST = env.str('EMAIL_HOST', default='localhost')
EMAIL_PORT = env.int('EMAIL_PORT', default=25)
# Login for access to SMTP-server
EMAIL_HOST_USER = env.str('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = env.bool('EMAIL_USE_TLS', default=True)
EMAIL_BACKEND = env.str(
'EMAIL_BACKEND',
default='django.core.mail.backends.smtp.EmailBackend'
)
Плюсы:
- Разные конфиги для development/production.
- Настройки можно легко менять на лету через переменные окружения.
- Чувствительные данные хранятся отдельно.
- Судя по гитхабу это весьма распространенное решение.
Минусы:
- Не уверен, насколько это безопасно.
- Много файлов - 5 вместо одного.
- Читабельность настроек сильно — я бы даже сказал фатально — упала.
# .secrets.toml содержит все чувствительные данные(добавлен в .gitignore). Я решил что будет логично оставить
# его в корне проекта(мне спокойнее когда я не вижу его в корне публичного репозитория).
.secrets.toml
# Мне показалось рациональным добавить к директориям приложений префикс `app_`.
app_first/
app_second/
...
base_project_dir/
config/ # Все конфиги проекта хранятся в одной отдельной директории.
├── __init__.py
├── settings/
│ ├── settings.py # Базовые настройки
│ ├── development.toml
│ └── production.toml
├── urls.py
└── wsgi.py
...
manage.py
[development]
# General
# -----------------------------------------------------------------------------
SECRET_KEY = '<development_secret_key>'
[production]
# General
# -----------------------------------------------------------------------------
SECRET_KEY = '<production_secret_key>'
# PostgreSQL
# ------------------------------------------------------------------------------
DATABASES__default__USER = '<postgresql_username>'
DATABASES__default__PASSWORD='<postgresql_password>'
import os
import dynaconf
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Applications
#------------------------------------------------------------------------------
INSTALLED_APPS = [
'account.apps.AccountConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'bookmarks.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'bookmarks.wsgi.application'
# Password validation
#------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Log-in
#------------------------------------------------------------------------------
LOGIN_REDIRECT_URL = 'dashboard'
LOGIN_URL = 'login'
LOGOUT_URL = 'logout'
# Internationalization
#------------------------------------------------------------------------------
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Media
# -----------------------------------------------------------------------------
MEDIA_URL = '/media/'
settings = dynaconf.DjangoDynaconf(
__name__,
ENVVAR_PREFIX_FOR_DYNACONF='BOOKMARKS'
) # noqa
[development]
# General
# -----------------------------------------------------------------------------
DEBUG = true
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
# Applications
# -----------------------------------------------------------------------------
# https://django-extensions.readthedocs.io/en/latest/
INSTALLED_APPS = ["django_extensions", 'dynaconf_merge']
# Database
#------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES__default__ENGINE = 'django.db.backends.sqlite3'
DATABASES__default__NAME = '@format {this.BASE_DIR}/db.sqlite3'
# Static files
# -----------------------------------------------------------------------------
STATIC_URL = '/static/'
# Media files
# -----------------------------------------------------------------------------
MEDIA_ROOT = '@format {this.BASE_DIR}/media'
# Email
# -----------------------------------------------------------------------------
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'