Djangoでローカルと本番の設定を管理する方法は?


298

ローカル開発と本番サーバーの設定を処理するための推奨される方法は何ですか?それらの一部(定数など)は両方で変更/アクセスできますが、一部(静的ファイルへのパスなど)は異なるままにする必要があるため、新しいコードがデプロイされるたびに上書きしないでください。

現在、すべての定数をに追加していsettings.pyます。しかし、ローカルで定数を変更するたびに、それを運用サーバーにコピーし、運用固有の変更のためにファイルを編集する必要があります... :(

編集:この質問に対する標準的な答えはないようですが、私は最も一般的な方法を受け入れました。



django-configurationsをご覧ください。
JJD 2015年

2
受け入れられた方法は、もはや最も人気のある方法ではありません。
ダニエル

2
django-split-settingsは非常に使いやすいです。デフォルト設定を書き換える必要はありません。
2015年

yoは、base.pyファイルを使用し、local.py "from .base import *"でも、production.py "from .base import *"でも同じように使用する必要があります。次のコマンドでプロジェクトを実行する必要があります。python manage.py runserver- settings = project_name.settings.local
RoberthSolís、

回答:


127

settings.py

try:
    from local_settings import *
except ImportError as e:
    pass

で必要なものを上書きできますlocal_settings.py。その場合、バージョン管理の対象外になります。しかし、あなたはコピーについて言及しているので、私はあなたがどれも使用していないと思います;)


3
新しい設定の追跡/展開を容易にするために、本稼働/テストマシンでは「local_settings.py」を使用し、開発では使用しません。
John Mee

8
それが私がする方法です-それらがデフォルト設定を上書きできるようにsettings.pyの最後にそれらの行を追加します
daonb

61
このアプローチは、開発および本番環境でバージョン管理されていないコードが実行されていることを意味します。そして、すべての開発者は異なるコードベースを持っています。ここではアンチパターンと呼んでいます。
pydanny 2013年

8
@pydanny問題は、Djangoがその構成を.pyファイルに保存することです。すべての開発者と本番サーバーが同じ設定を使用することを期待することはできないため、この.pyファイルを変更するか、いくつかの代替ソリューション(.iniファイル、環境など)を実装する必要があります。
Tupteq 2013

3
アルファベット順のフォルダリストでグループ化するのではsettings_localなく、モジュールを呼び出すことを好みます。キープ使用して、バージョン管理のアウト資格情報は、Gitリポジトリに属していないよう。偶然にオープンソースを想像してください。代わりにgitというテンプレートファイルを保持します。local_settingssettings.pysettings_local.py.gitignoresettings_local.py.txt
改行

297

Djangoの2つのスクープ:Django 1.5のベストプラクティスでは、設定ファイルのバージョン管理を使用し、ファイルを別のディレクトリに保存することをお勧めします。

project/
    app1/
    app2/
    project/
        __init__.py
        settings/
            __init__.py
            base.py
            local.py
            production.py
    manage.py

base.py中にファイルは、(例えばMEDIA_ROOTまたはADMINなど)の一般的な設定が含まれていますlocal.pyし、production.pyサイト固有の設定があります。

ベースファイルsettings/base.py

INSTALLED_APPS = (
    # common apps...
)

ローカル開発設定ファイルsettings/local.py

from project.settings.base import *

DEBUG = True
INSTALLED_APPS += (
    'debug_toolbar', # and other apps for local development
)

ファイル作成設定ファイルsettings/production.py

from project.settings.base import *

DEBUG = False
INSTALLED_APPS += (
    # other apps for production site
)

次に、djangoを実行するときに、--settingsオプションを追加します。

# Running django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local

# Running django shell on the production site
$ ./manage.py shell --settings=project.settings.production

この本の作者も我慢してきた サンプルプロジェクトレイアウトテンプレートをGithubにも公開しています。


62
--settings毎回使用する代わりに、DJANGO_SETTINGS_MODULEenvvarを設定できることに注意してください。これは、Herokuなどでうまく機能します。グローバルに本番に設定し、.envファイルのdevでオーバーライドします。
Simon Weber

9
DJANGO_SETTINGS_MODULEここでは、env var を使用するのが最善の方法です。Simonに感謝します。
kibibu 2013年

20
あなたは変更する必要がありますBASE_DIRに設定をos.path.dirname(os.path.realpath(os.path.dirname(__file__) + "/.."))
ペトルペラ

5
django docsに従って@rspをインポートfrom django.conf import settingsします。これは、インターフェースを抽象化し、設定の場所からコードを分離するオブジェクトです。docs.djangoproject.com

3
環境変数を介してDJANGO_SETTINGS_MODULEを設定した場合でも、wsgi.pyファイルにos.environ.setdefault( "DJANGO_SETTINGS_MODULE"、 "projectname.settings.production")が必要ですか?また、export DJANGO_SETTINGS_MODULE = projectname.settings.localを使用して環境変数を設定しましたが、ターミナルを閉じると失われます。確実に保存するにはどうすればよいですか?その行をbashrcファイルに追加する必要がありますか?
Kritz 2014年

71

の代わりにsettings.py、次のレイアウトを使用します。

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py ほとんどの構成が存在する場所です。

prod.py commonからすべてをインポートし、オーバーライドする必要があるものはすべてオーバーライドします。

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

同様に、dev.pyからすべてをインポートしcommon.py、オーバーライドする必要があるものはすべてオーバーライドします。

最後に、__init__.pyロードする設定を決定する場所であり、シークレットを格納する場所でもあります(したがって、このファイルはバージョン管理しないでください)。

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### DJANGO SECRETS
SECRET_KEY = '(3gd6shenud@&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

このソリューションについて私が好きなのは:

  1. シークレットを除くすべてがバージョン管理システムにあります
  2. ほとんどの設定は1か所にありますcommon.py
  3. 製品固有のものはprod.py、開発固有のものはに入りdev.pyます。それは簡単です。
  4. あなたは、からのものを上書きすることができますcommon.pyprod.pydev.py、あなたはで何かを上書きすることができます__init__.py
  5. 簡単なpythonです。再インポートのハックはありません。

2
設定ファイルのproject.wsgiファイルとmanage.pyファイルに何を設定するかをまだ理解しようとしています。これに光を当ててくれませんか?具体的には、私のmanage.pyファイルでは、os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings")foob​​arはファイルを含む__init__.pyフォルダーであり、settingsは__init__.py私のシークレットを含むファイルを含むフォルダーであり、dev.pyをインポートして、common.pyをインポートします。 編集気にしないで、必要なモジュールがインストールされていません。悪い!これはうまくいきます!!
teewuane 2014

5
2つのこと:1)dev.pyで= Falseではなく、dev.pyでDebug = Trueを設定する方が良い。2)init .pyで切り替えるのではなく、DJANGO_SETTINGS_MODULE環境変数を使用して切り替えます。これは、PAAS展開(Herokuなど)に役立ちます。
Rob Grant

この設定をdjango 1.8.4で使用してrunserverを試すと、「django.core.exceptions.ImproperlyConfigured:SECRET_KEY設定を空にすることはできません。」というメッセージが表示されますが、init .pyファイルにSECRET_KEYがあります。何か不足していますか?
polarcare 2015

AWS_SECRET_ACCESS_KEY = os.getenv( "AWS_SECRET_ACCESS_KEY")のようなものを使用する方が安全ではありませんか?正直な質問-バージョン管理を望まない理由はわかっていますが、他の選択肢は、環境から取得することです。もちろん、どちらが環境変数の設定の問題を引き起こしますが、それはデプロイメントメカニズムに任せることができますか?
JL Peyret 2015

20

Harper Shelbyが投稿した「if DEBUG」スタイルの設定を少し変更したバージョンを使用しています。明らかに環境(win / linux / etc)によっては、コードを少し調整する必要があるかもしれません。

以前は「if DEBUG」を使用していましたが、DEUBGをFalseに設定してテストを実行する必要がある場合があることに気付きました。環境が本番環境か開発環境かを本当に区別したかったので、DEBUGレベルを自由に選択できました。

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG

# ...

if PRODUCTION:
    DATABASE_HOST = '192.168.1.1'
else:
    DATABASE_HOST = 'localhost'

この設定方法はまだ進行中の作業と考えています。私はすべてのベースをカバーするDjango設定を処理する方法を1つも見たことがなく、同時に設定するのが面倒ではありませんでした(私は5x設定ファイルの方法に夢中ではありません)。


これは、実際のコードファイルであるDjangoの設定が許可する種類のものであり、私はほのめかしていました。私は自分でこのようなことを何もしていませんが、それは間違いなく私の種類よりも良い一般的な答えかもしれない種類のソリューションです。
ハーパーシェルビー

3
私はこれに初めて遭遇し、(成功!)ソリューションを使用することを選択しましたが、わずかな違いがあります。私はuuid.getnode()を使用してシステムのuuidを見つけました。だから私はあなたが使用したos.environテストの代わりにuuid.getnode()== 12345678901(実際には別の数)かどうかをテストしています。os.environ ['COMPUTERNAME']はコンピューターごとに固有であることを納得させる文書が見つかりませんでした。
Joe Golton、

os.environ ['COMPUTERNAME']は、Amazon AWS Ubuntuでは機能しません。KeyErrorが発生します。
nu everest 2014年

UUIDを使用する場合、このソリューションは私にとって最良かつ最も簡単であることが証明されています。それは多くの複雑で過剰にモジュール化されたパッチワークを必要としません。本番環境では、データベースのパスワードとSECRET_KEYを、バージョン管理外にある別のファイルに配置する必要があります。
nu everest 2014年

os.environ['COMPUTERNAME']残念ながらPythonAnywhereでは動作しません。KeyErrorが発生します。
nbeuchat 2017年

14

私はsettings_local.pyとsettings_production.pyを使用しています。いくつかのオプションを試した後、2つの設定ファイルがあるだけで簡単かつ高速に感じると、複雑なソリューションで時間を浪費するのが簡単であることがわかりました。

Djangoプロジェクトにmod_python / mod_wsgiを使用する場合は、設定ファイルを指定する必要があります。ローカルサーバーでapp / settings_local.pyを、本番サーバーでapp / settings_production.pyを指定すると、作業が楽になります。適切な設定ファイルを編集してサーバーを再起動するだけです(Django開発サーバーは自動的に再起動します)。


2
そして、ローカル開発サーバーはどうですか?python manage.py runserver使用する設定ファイルをdjangoウェブサーバー(を使用して実行)に通知する方法はありますか?
akv 2009年

2
@akv runserverコマンドの最後に--settings = [モジュール名](.py拡張子なし)を追加すると、使用する設定ファイルを指定できます。それを行うつもりなら、自分でお願いして、開発設定が構成されたシェルスクリプト/バッチファイルを作成してください。信頼してください、あなたの指はあなたに感謝します。
T. Stone、

これは私が使用するソリューションです。本番
環境と

4
常に指定する必要がないため、開発ではsettings.pyを使用する方が良いと思います。
Andre Bossard、2010

この方法では、プロキシdjango.conf.settingsを介して設定モジュールをインポートする必要があると仮定しても正しいですか?それ以外の場合は、ライブをプッシュするときに正しい設定ファイルを指すようにインポート宣言を編集する必要があります。
Groady、2011年

8

TL; DR:トリックは変更することでos.environment、インポートする前にsettings/base.pyいずれかでsettings/<purpose>.py、これは非常に物事を単純化します。


これらすべての絡み合うファイルについて考えるだけで頭痛の種になります。DEBUG後で設定が変更された場合に備えて、すでに設定されているものの結合、インポート(場合によっては条件付き)、上書き、パッチ適用。なんて悪夢なんだ!

私は何年にもわたって、さまざまなソリューションをすべて試しました。それらはすべて多少は機能しますが、管理が非常に困難です。WTF!本当に面倒なことすべてが必要なのでしょうか?最初は1つのsettings.pyファイルから始めました。これらすべてを正しい順序で正しく組み合わせるためのドキュメントが必要です!

私は最終的に以下の解決策で(私の)スイートスポットを打つことを望みます。

目標を要約しましょう(いくつかの一般的なもの、いくつかの私のもの)

  1. 秘密は秘密にしてください—リポジトリに保存しないでください!

  2. 環境設定を介してキーとシークレットを設定/読み取り、12要素スタイル

  3. 賢明なフォールバックのデフォルトがある。ローカル開発では、デフォルト以外に何も必要ないのが理想的です。

  4. …しかし、デフォルトのプロダクションを安全に保つようにしてください。本番環境で安全にデフォルト設定を調整することを覚えておかなければならないより、ローカルで設定のオーバーライドを見逃した方がよいです。

  5. DEBUG他の設定に影響を与える可能性のある方法で(たとえば、JavaScriptの圧縮を使用するかどうかを問わず)オン/オフを切り替えることができます。

  6. ローカル、テスト、ステージング、本番などの目的設定の切り替えは、のみに基づいて行う必要がありDJANGO_SETTINGS_MODULEます。

  7. …しかし、などの環境設定を介してさらにパラメータ化を許可しますDATABASE_URL

  8. …また、さまざまな目的の設定を使用して、ローカルで並べて実行することもできます。ローカルの開発者マシンでのプロダクション設定。プロダクションデータベースまたはスモークテストの圧縮スタイルシートにアクセスします。

  9. 環境変数が明示的に設定されていない場合(少なくとも空の値が必要)、特に本番環境では失敗します。EMAIL_HOST_PASSWORD

  10. django-admin startprojectDJANGO_SETTINGS_MODULE中にmanage.pyで設定されたデフォルトに応答する

  11. 条件がある場合は、最小限に条件文を保つ目的と環境タイプ(例。制作・セット・ログ・ファイルとそれの回転のために)、関連する目的と、設定ファイルで上書き設定が。

しない

  1. djangoにDJANGO_SETTINGS_MODULE設定をファイルから読み取らせないでください。
    うわっ!これがどれほどメタかを考えてください。ファイル(docker envなど)が必要な場合は、djangoプロセスを開始する前にそれを環境に読み込みます。

  2. プロジェクトやアプリのコードでDJANGO_SETTINGS_MODULEをオーバーライドしないでください。ホスト名またはプロセス名に基づく。
    (のようにsetup.py test)環境変数を設定するのが面倒な場合は、プロジェクトコードを実行する直前にツールで設定してください。

  3. djangoが設定を読み取る方法の魔法やパッチを避け、設定を前処理しますが、後で干渉しないでください。

  4. 複雑なロジックベースのナンセンスはありません。構成は、オンザフライで計算されずに修正および実体化する必要があります。ここでは、フォールバックのデフォルトを提供するだけで十分なロジックです。
    本当にデバッグしますか?ローカルに正しい設定セットがあるのに、リモートサーバーの運用環境で、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 *

ここで重要なのはDEBUGASSETS_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環境設定でオーバーライドすることもできます!わーい!

実際には、重要性の混合階層があります。

  1. settings / .py-目的に基づいてデフォルトを設定し、シークレットを保存しません
  2. settings / base.py-主に環境によって制御されます
  3. プロセス環境設定-12要素の赤ちゃん!
  4. settings / .env-起動が簡単なローカルデフォルト

ヤヌスさん... .envファイルでは、すべてのAPIキー、認証キー、パスワードなどを取得しますか?TWILLIO_API = "abc123"のように?またはTWILLIO_API = env( "TWILLIO_API")?
dbinott 2018

はい。ただし、これは環境設定のフォールバックにすぎません。このファイルは開発に便利ですが、リポジトリに保存したり、本番環境にプッシュしたりすることはありません。サーバー環境の設定を厳密に行う環境設定または同等のプラットフォームを厳密に使用する必要があります。
Janusz Skonieczny

7

私はdjango-split-settingsを利用して設定を管理しています

これは、デフォルト設定のドロップイン置換です。シンプルですが、構成可能です。また、既存の設定のリファクタリングは必要ありません。

以下に小さな例(ファイルexample/settings/__init__.py)を示します。

from split_settings.tools import optional, include
import os

if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
    include(
        'components/default.py',
        'components/database.py',
        # This file may be missing:
        optional('local_settings.py'),

        scope=globals()
    )

それでおしまい。

更新

での設定の管理に関するブログ投稿を書きました。見てください!djangodjango-split-sttings


1
私は私が私のDjangoのユニットテストを実行しようとしたら、壁にその..走ってみました..私はちょうどから読み取るためにどの設定ファイルを指定する方法を見つけ出すことができませんでした
abbood

私はあなたのために要点を作成しました:gist.github.com/sobolevn/006c734f0520439a4b6c16891d65406c
sobolevn

私はコードでこのようなものを得たので、settings.DEBUGフラグをチェックして、何かをインポートするかどうかを確認します..このフラグは、djangoユニットテスト(ここを参照)で常にfalseに設定されているので、それぞれのテストはそのように
16

ここで別の質問ですが、私のuwsgi.iniファイルにはdev / prod全体で異なる設定があります。設定ファイルから値を選択させる方法についてのアイデアはありますか?
16

申し訳ありませんが、セットアップを取得できません。あなたはより詳細な別の質問をすることができ、私はあなたを助けようとします。
sobolevn 2016

6

これらのソリューションのほとんどの問題は、一般的な設定のまたは後でローカル設定を適用することです。

したがって、次のようなものをオーバーライドすることは不可能です

  • 環境固有の設定はmemcachedプールのアドレスを定義し、メイン設定ファイルではこの値を使用してキャッシュバックエンドを構成します
  • 環境固有の設定により、アプリ/ミドルウェアをデフォルトに追加または削除します

同時に。

1つのソリューションは、ConfigParserクラスで「ini」スタイルの構成ファイルを使用して実装できます。複数のファイル、遅延文字列補間、デフォルト値、その他多くの機能をサポートしています。多数のファイルがロードされると、より多くのファイルをロードでき、それらの値は以前のファイルがあればそれを上書きします。

マシンアドレス、環境変数、および以前にロードされた構成ファイルの値に応じて、1つ以上の構成ファイルをロードします。次に、解析された値を使用して設定を入力します。

私がうまく使用した1つの戦略は次のとおりです。

  • デフォルトのdefaults.iniファイルをロードする
  • マシン名を確認し、逆のFQDNに一致したすべてのファイルを、最短一致から最長一致までロードします(したがって、をロードしnet.ini、次にnet.domain.ini、次にnet.domain.webserver01.ini、それぞれが前の値をオーバーライドしている可能性があります)。このアカウントは開発者のマシンにも対応しているため、それぞれがローカル開発用の優先データベースドライバーなどをセットアップできます。
  • 「クラスター名」が宣言されているかどうかを確認します。その場合cluster.cluster_name.ini、データベースやキャッシュIPなどを定義できるload があります。

これで達成できることの例として、envごとに「サブドメイン」値を定義できます。これは、デフォルト設定(としてhostname: %(subdomain).whatever.net)で使用され、djangoが機能するために必要なすべてのホスト名とCookieを定義します。

これは私が得ることができるDRYであり、ほとんどの(既存の)ファイルには3つまたは4つの設定しかありませんでした。これに加えて、お客様の構成を管理する必要があったため、追加の構成ファイルのセット(データベース名、ユーザーとパスワード、割り当てられたサブドメインなど)が、顧客ごとに1つ以上存在しました。

これを必要に応じて低くまたは高くスケーリングできます。環境ごとに構成するキーを構成ファイルに入れ、新しい構成が必要な場合は、以前の値をデフォルトの構成に入れてオーバーライドします。必要な場合。

このシステムは信頼性が証明されており、バージョン管理とうまく連動します。これは、2つの個別のアプリケーションクラスタ(マシンごとにdjangoサイトの15以上の個別のインスタンス)を長期にわたって管理するために使用され、sysadminの気分に応じてクラスタのサイズとメンバーが変化していた50を超える顧客でした。 。


1
iniからDjangoの設定に設定をロードする方法の例はありますか?
kaleissin 2013年

docs.python.org/2/library/configparser.htmlを参照してください。でパーサーをロードしconfig = ConfigParser.ConfigParser() てファイルconfig.read(array_of_filenames)を読み取り、を使用して値を取得できますconfig.get(section, option)。したがって、最初に構成をロードし、次にそれを使用して設定の値を読み取ります。
書き換え

5

私はLaravelとも協力しており、そこでの実装が気に入っています。私はそれを模倣して、T。ストーンによって提案されたソリューションと組み合わせようとしました(上記を参照):

PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]

def check_env():
    for item in PRODUCTION_SERVERS:
        match = re.match(r"(^." + item + "$)", socket.gethostname())
        if match:
            return True

if check_env():
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION

多分このような何かがあなたを助けるでしょう。


4

settings.pyはライブコードファイルであることを忘れないでください。本番環境にDEBUGが設定されていないと(これがベストプラクティスです)、次のようなことができます。

if DEBUG:
    STATIC_PATH = /path/to/dev/files
else:
    STATIC_PATH = /path/to/production/files

かなり基本的ですが、理論的には、DEBUGの値、または使用したい他の変数やコードのチェックだけに基づいて、あらゆるレベルの複雑さを実現できます。


4

ほとんどのプロジェクトでは、次のパターンを使用しています。

  1. すべての環境に共通の設定を保存するsettings_base.pyを作成します
  2. 特定の要件を持つ新しい環境を使用する必要があるときはいつでも、settings_base.pyの内容を継承し、適切な設定変数を上書き/追加する新しい設定ファイル(たとえば、settings_local.py)を作成します(from settings_base import *

(あなたは、単に--settingsコマンドオプションを使用するファイルのカスタム設定でmanage.pyを実行するにはmanage.py <command> --settings=settings_you_wish_to_use.py


3

その問題に対する私の解決策は、すでにここで述べられているいくつかの解決策の組み合わせでもあります。

  • 私はdevとprodにlocal_settings.pyコンテンツを含むというファイルを保持していますUSING_LOCAL = TrueUSING_LOCAL = False
  • settings.py、私はそのファイルにインポートを行う取得するUSING_LOCAL設定を

次に、環境に依存するすべての設定をその設定に基づいています。

DEBUG = USING_LOCAL
if USING_LOCAL:
    # dev database settings
else:
    # prod database settings

設定を複数のファイルに分散させるよりも1つのファイルで簡単に構造化できるため、維持する必要がある2つの個別のsettings.pyファイルを使用するよりも、これを好みます。このように、両方の環境で設定を更新することを忘れないでください。

もちろん、どの方法にも欠点があり、これも例外ではありません。ここでの問題はlocal_settings.py、変更を本番環境にプッシュするたびにファイルを上書きできないことです。つまり、すべてのファイルをブラインドコピーするだけではなく、それでも問題ありません。


3

上記のjpartogiのバリエーションを使用しますが、少し短くなっています。

import platform
from django.core.management import execute_manager 

computername = platform.node()

try:
  settings = __import__(computername + '_settings')
except ImportError: 
  import sys
  sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
  sys.exit(1)

if __name__ == "__main__":
  execute_manager(settings)

基本的に、各コンピューター(開発または本番)で、動的にロードされる適切なhostname_settings.pyファイルがあります。



3

1-アプリ内に新しいフォルダーを作成し、設定に名前を付けます。

2-次に新しい__init__.pyファイルを作成し、その中に書き込みます

from .base import *

try:
    from .local import *
except:
    pass

try:
    from .production import *
except:
    pass

3-設定フォルダ名local.pyproduction.pyおよびに3つの新しいファイルを作成しますbase.py

4-内部でbase.py、前のsettings.pyフォルダのすべてのコンテンツをコピーし、別の名前に変更しますold_settings.py

5-base.pyで、設定の新しいパスを指すようにBASE_DIRパスを変更します

古いパス-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

新しいパス-> BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

このようにして、プロジェクトディレクトリを構造化し、プロダクションとローカル開発の間で管理できます。


2

settings異なる環境で異なる構成を使用するには、異なる設定ファイルを作成します。そして、デプロイメントスクリプトで、--settings=<my-settings.py>パラメーターを使用してサーバーを起動します。これにより、さまざまな環境でさまざまな設定を使用できます。

このアプローチを使用する利点

  1. 設定は、各環境に基づいてモジュール化されます

  2. master_settings.py基本設定を含むをインポートし、environmnet_configuration.pyその環境で変更する値を上書きできます。

  3. あなたが巨大なチームを持っている場合、各開発者はlocal_settings.py、サーバー構成を変更するリスクなしにコードリポジトリに追加できる独自のチームを持っている可能性があります。あなたはこれらのローカル設定を追加することができ.gitnore、あなたが使用している場合はgitの.hginoreどうかMercurialのためのバージョン管理(またはその他)。そうすれば、ローカル設定は実際のコードベースの一部にさえなりません。


2

次のように設定を分割しました

settings/
     |
     |- base.py
     |- dev.py
     |- prod.py  

3つの環境があります

  • 開発者
  • 演出
  • 製造

これで、ステージングとプロダクションは、可能な限り同じような環境になるはずです。したがってprod.py、両方を維持しました。

しかし、稼働中のサーバーが本番サーバーであることを確認しなければならない場合がありました。@T。Stoneの回答は、次のように小切手を書くのに役立ちました。

from socket import gethostname, gethostbyname  
PROD_HOSTS = ["webserver1", "webserver2"]

DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]


if any(host in PROD_HOSTS for host in ALLOWED_HOSTS):
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True  

1

私はそれをmanage.pyで区別し、2つの個別の設定ファイルを作成しました:local_settings.pyとprod_settings.py。

manage.pyで、サーバーがローカルサーバーか本番サーバーかを確認します。ローカルサーバーの場合はlocal_settings.pyを読み込み、本番サーバーの場合はprod_settings.pyを読み込みます。基本的には次のようになります。

#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager 

ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
    try:
        import local_settings # Assumed to be in the same directory.
        settings = local_settings
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)
else:
    try:
        import prod_settings # Assumed to be in the same directory.
        settings = prod_settings    
    except ImportError:
        import sys
        sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
        sys.exit(1)

if __name__ == "__main__":
    execute_manager(settings)

設定ファイル内で多数のifを実行するよりも、設定ファイルを2つの個別のファイルに分割する方が簡単であることがわかりました。


1

wiilした場合に別のファイルを維持する代わりに、gitまたは他のVCSを使用してローカルからサーバーにコードをプッシュする場合、設定ファイルを.gitignoreに追加することで実行できます。

これにより、問題なく両方の場所で異なるコンテンツを使用できます。サーバーでSOを使用すると、settings.pyの独立したバージョンを構成できます。ローカルで行った変更はサーバーには反映されず、その逆も同様です。

さらに、githubからsettings.pyファイルも削除されます。これは、多くの初心者が行っている大きな障害です。



0

@Tが最善の解決策を提案していると思います。ストーンですが、なぜDjangoでDEBUGフラグを使用しないのかわかりません。私は私のウェブサイトのために以下のコードを書きます:

if DEBUG:
    from .local_settings import *

常にシンプルなソリューションは複雑なソリューションよりも優れています。


-2

ここでの回答はとても役に立ちました。(これはより確実に解決されましたか?最後の応答は1年前でした。)リストされたすべてのアプローチを検討した後、私はここにリストされていないソリューションを思いつきました。

私の基準は:

  • すべてがソース管理にある必要があります。あちこちうそをついているのは好きではない。
  • 理想的には、設定を1つのファイルに保存します。それらを正しく見ていなければ、物事を忘れてしまいます:)
  • 展開する手動の編集はありません。1つのファブリックコマンドでテスト、プッシュ、デプロイできる必要があります。
  • 開発設定を本番環境にリークしないでください。
  • "標準"(* cough *)Djangoレイアウトにできるだけ近づけてください。

ホストマシンのスイッチを入れるのは理にかなっていると思いましたが、ここで本当の問題はさまざまな環境のさまざまな設定であることがわかりました。このコードをsettings.pyファイルの最後に配置します。

try:
    os.environ['DJANGO_DEVELOPMENT_SERVER'] # throws error if unset
    DEBUG = True
    TEMPLATE_DEBUG = True
    # This is naive but possible. Could also redeclare full app set to control ordering. 
    # Note that it requires a list rather than the generated tuple.
    INSTALLED_APPS.extend([
        'debug_toolbar',
        'django_nose',
    ])
    # Production database settings, alternate static/media paths, etc...
except KeyError: 
    print 'DJANGO_DEVELOPMENT_SERVER environment var not set; using production settings'

このように、アプリはデフォルトで本番環境設定になります。つまり、開発環境を明示的に「ホワイトリストに登録」します。環境変数をローカルに設定することを忘れた方が、逆の場合よりも安全であり、本番環境で何かを設定するのを忘れて、いくつかの開発設定を使用させることができます。

ローカルで開発する場合、シェルから、または.bash_profileのどこかで:

$ export DJANGO_DEVELOPMENT_SERVER=yep

(または、Windowsで開発している場合は、コントロールパネルまたは最近の名称で設定します。Windowsでは、環境変数を設定できるように、常にあいまいになっています。)

このアプローチでは、開発設定はすべて1つ(標準)の場所にあり、必要に応じて本番環境の設定をオーバーライドします。開発設定をいじくり回しても、本番環境に影響を与えることなく、ソース管理にコミットしても完全に安全でなければなりません。


異なる構成ファイルを維持し、DJango標準環境変数DJANGO_SETTINGS_MODULEを使用して選択する方が良い
Rob Grant
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.