TL; DR:トリックは変更することでos.environment
、インポートする前にsettings/base.py
いずれかでsettings/<purpose>.py
、これは非常に物事を単純化します。
これらすべての絡み合うファイルについて考えるだけで頭痛の種になります。DEBUG
後で設定が変更された場合に備えて、すでに設定されているものの結合、インポート(場合によっては条件付き)、上書き、パッチ適用。なんて悪夢なんだ!
私は何年にもわたって、さまざまなソリューションをすべて試しました。それらはすべて多少は機能しますが、管理が非常に困難です。WTF!本当に面倒なことすべてが必要なのでしょうか?最初は1つのsettings.py
ファイルから始めました。これらすべてを正しい順序で正しく組み合わせるためのドキュメントが必要です!
私は最終的に以下の解決策で(私の)スイートスポットを打つことを望みます。
目標を要約しましょう(いくつかの一般的なもの、いくつかの私のもの)
秘密は秘密にしてください—リポジトリに保存しないでください!
環境設定を介してキーとシークレットを設定/読み取り、12要素スタイル。
賢明なフォールバックのデフォルトがある。ローカル開発では、デフォルト以外に何も必要ないのが理想的です。
…しかし、デフォルトのプロダクションを安全に保つようにしてください。本番環境で安全にデフォルト設定を調整することを覚えておかなければならないより、ローカルで設定のオーバーライドを見逃した方がよいです。
DEBUG
他の設定に影響を与える可能性のある方法で(たとえば、JavaScriptの圧縮を使用するかどうかを問わず)オン/オフを切り替えることができます。
ローカル、テスト、ステージング、本番などの目的設定の切り替えは、のみに基づいて行う必要がありDJANGO_SETTINGS_MODULE
ます。
…しかし、などの環境設定を介してさらにパラメータ化を許可しますDATABASE_URL
。
…また、さまざまな目的の設定を使用して、ローカルで並べて実行することもできます。ローカルの開発者マシンでのプロダクション設定。プロダクションデータベースまたはスモークテストの圧縮スタイルシートにアクセスします。
環境変数が明示的に設定されていない場合(少なくとも空の値が必要)、特に本番環境では失敗します。EMAIL_HOST_PASSWORD
。
django-admin startprojectDJANGO_SETTINGS_MODULE
中にmanage.pyで設定されたデフォルトに応答する
条件がある場合は、最小限に条件文を保つ目的と環境タイプ(例。制作・セット・ログ・ファイルとそれの回転のために)、関連する目的と、設定ファイルで上書き設定が。
しない
djangoにDJANGO_SETTINGS_MODULE設定をファイルから読み取らせないでください。
うわっ!これがどれほどメタかを考えてください。ファイル(docker envなど)が必要な場合は、djangoプロセスを開始する前にそれを環境に読み込みます。
プロジェクトやアプリのコードでDJANGO_SETTINGS_MODULEをオーバーライドしないでください。ホスト名またはプロセス名に基づく。
(のようにsetup.py test
)環境変数を設定するのが面倒な場合は、プロジェクトコードを実行する直前にツールで設定してください。
djangoが設定を読み取る方法の魔法やパッチを避け、設定を前処理しますが、後で干渉しないでください。
複雑なロジックベースのナンセンスはありません。構成は、オンザフライで計算されずに修正および実体化する必要があります。ここでは、フォールバックのデフォルトを提供するだけで十分なロジックです。
本当にデバッグしますか?ローカルに正しい設定セットがあるのに、リモートサーバーの運用環境で、100台のマシンのうちの1台で計算が異なるのはなぜですか?ああ!ユニットテスト?設定は?マジ?
解決
私の戦略は、優れたで構成されていジャンゴ・環境で使用ini
提供し、スタイルファイルos.environment
のローカル開発のためのデフォルト、いくつかの最低限の短いsettings/<purpose>.py
持つファイル
import settings/base.py
AFTERos.environment
から設定されたINI
ファイルを。これは事実上、一種の設定インジェクションを提供します。
ここでの秘訣は、os.environment
インポートする前に変更することですsettings/base.py
。
完全な例を確認するには、レポを実行してください:https : //github.com/wooyek/django-settings-strategy
.
│ manage.py
├───data
└───website
├───settings
│ │ __init__.py <-- imports local for compatibility
│ │ base.py <-- almost all the settings, reads from proces environment
│ │ local.py <-- a few modifications for local development
│ │ production.py <-- ideally is empty and everything is in base
│ │ testing.py <-- mimics production with a reasonable exeptions
│ │ .env <-- for local use, not kept in repo
│ __init__.py
│ urls.py
│ wsgi.py
設定/.env
ローカル開発のデフォルト。必要な環境変数をほとんど設定するための秘密ファイル。ローカル開発で必要ない場合は、空の値に設定してください。ここにデフォルトを提供settings/base.py
し、環境にない場合に他のマシンで失敗しないようにします。
設定/local.py
ここで何が起こるかは、から環境をロードしsettings/.env
、次にから共通設定をインポートすることsettings/base.py
です。その後、ローカル開発を容易にするためにいくつかをオーバーライドできます。
import logging
import environ
logging.debug("Settings loading: %s" % __file__)
# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')
from .base import *
ALLOWED_HOSTS += [
'127.0.0.1',
'localhost',
'.example.com',
'vagrant',
]
# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
LOGGING['handlers']['mail_admins']['email_backend'] = 'django.core.mail.backends.dummy.EmailBackend'
# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager
CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
settings / production.py
本番環境では環境ファイルを期待するべきではありませんが、何かをテストする場合は環境ファイルを用意する方が簡単です。ただし、とにかく、インラインではデフォルトがほとんど提供されないため、それにsettings/base.py
応じて応答できます。
environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *
ここで重要なのはDEBUG
、ASSETS_DEBUG
オーバーライドでありos.environ
、環境とファイルから欠落している場合にのみPythonに適用されます。
これらは本番環境のデフォルトであり、環境やファイルに配置する必要はありませんが、必要に応じて上書きできます。きちんと!
settings / base.py
これらは、ほとんどバニラのdjango設定であり、いくつかの条件付きで、環境からそれらをたくさん読み取ります。ほとんどすべてがここにあり、すべての目的の環境に一貫性を保ち、可能な限り類似しています。
主な違いは以下のとおりです(これらが自明であることを願っています)。
import environ
# https://github.com/joke2k/django-environ
env = environ.Env()
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Where BASE_DIR is a django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your django project code is in `src` folder
# This may help to separate python modules and *django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)
INTERNAL_IPS = [
'127.0.0.1',
]
ALLOWED_HOSTS = []
if 'ALLOWED_HOSTS' in os.environ:
hosts = os.environ['ALLOWED_HOSTS'].split(" ")
BASE_URL = "https://" + hosts[0]
for host in hosts:
host = host.strip()
if host:
ALLOWED_HOSTS.append(host)
SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
if "DATABASE_URL" in os.environ: # pragma: no cover
# Enable database config through environment
DATABASES = {
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
'default': env.db(),
}
# Make sure we use have all settings we need
# DATABASES['default']['ENGINE'] = 'django.contrib.gis.db.backends.postgis'
DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
DATABASES['default']['OPTIONS'] = {
'options': '-c search_path=gis,public,pg_catalog',
'sslmode': 'require',
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
'TEST': {
'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
}
}
}
STATIC_ROOT = os.path.join(ROOT_DIR, 'static')
# django-assets
# http://django-assets.readthedocs.org/en/latest/settings.html
ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG) # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
ASSETS_URL = STATIC_URL
ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
ASSETS_URL = STATIC_URL + "assets/compressed/"
ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)
最後のビットはここで力を示しています。ASSETS_DEBUG
には適切なデフォルトがあり、それをオーバーライドすることもでき、それをsettings/production.py
環境設定でオーバーライドすることもできます!わーい!
実際には、重要性の混合階層があります。
- settings / .py-目的に基づいてデフォルトを設定し、シークレットを保存しません
- settings / base.py-主に環境によって制御されます
- プロセス環境設定-12要素の赤ちゃん!
- settings / .env-起動が簡単なローカルデフォルト