Two Scoops Djangoが推奨するSettingsとRequirementsファイル設定

9573 ワード

基本原則
Django 1.8にはsettingsモジュールで設定できる約140の構成項目があります.settingsモジュールはDjangoサービスを起動するたびに初期化するのでsettings.pyファイルの変更後、Djangoサーバを再起動してから有効になります.
  • すべてのsettingsファイルは、構成項目の変更日時および注釈情報のバージョン制御
  • を含むバージョン制御を行うべきである.
  • DRYは、import base_settingsにより継承する、コピー貼付
  • を回避する.
  • 機密情報はバージョン管理の
  • に置かないでください.
    複数のsettingsファイルの使用
    settings/
        __init__.py
        base.py
        local.py
        staging.py
        test.py
        production.py

    各settingsファイルにはrequirementsファイルが対応しています
    settingsファイル名
    目的
    local.py, dev.py DEBUG=True、django-debug-toolbarなどのローカル開発環境構成コンテンツ
    staging.py
    Stagingフェーズの構成内容
    test.py
    テストを実行するための構成内容
    production.py, prod.py
    本番環境での構成内容
    ci.py
    継続的統合サーバの構成内容
    使用方法:
  • shell中
  • python manage.py shell --settings=twoscoops.settings.local
  • サービス
  • を開始
    python manage.py runserver --settings=twoscoops.settings.local
  • DJANGOを設定_SETTINGS_MODULEとPYTHONPATH環境変数.virtualenvを使用すると、環境ごとのアクティブ化スクリプトでDJANGO_を設定できます.SETTINGS_MODULEとPYTHONPATH.

  • 開発環境のsettingsファイルの例:
    # settings/local.py
    from .base import *
    
    DEBUG = True
    
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql_psycopg2",
            "NAME": "twoscoops",
            "USER": "",
            "PASSWORD": "",
            "HOST": "localhost",
            "PORT": "",
        }
    }
    
    INSTALLED_APPS += ("debug_toolbar", )

    上記の例にはfrom .base import *があり、これはimport *がDjangoで唯一使用に賛成された場所である.settingsファイルですべてのネーミングスペースを上書きしたいからです.
    開発環境に対してもsettingsファイルを複数作成できます
    基本原則は、settingsファイルごとにバージョン管理が必要です.次のような、さまざまな開発者向けのsettingsファイルを作成できます.
    # settings/dev_pydanny.py
    from .dev import *
    
    # Set short cache timeout
    CACHE_TIMEOUT = 30

    作成されたsettingsファイルは次のとおりです.
    settings/
        __init__.py
        base.py
        dev.py
        dev_audreyr.py
        dev_pydanny.py
        local.py
        staging.py
        test.py
        production.py

    構成情報をコードから分離する
    SECRET_KEY、API KEYなどの情報はコードライブラリに保存して以下の問題がある:
  • これらの情報は、導入のたびに
  • に変更されます.
  • SECRET_KEY等値は構成値であり、コード
  • ではない
  • はコードライブラリに格納されており、コードライブラリへのアクセス権のある人は
  • を見ることができます.
  • 多くのPaaSは、1台のサーバに対する構成機能
  • を提供しない.
    解決策は、環境変数を使用することです.
    環境変数を使用してSECRET_を保存KEY等の情報のメリット:
  • これらの機密情報が保存されているため、迷わずファイルごとにバージョン管理
  • を行います.
  • 配置ごとに、これらの構成情報を変更する必要がなくなりました.
  • PaaSプラットフォームの多くは、環境変数の使用を推奨し、対応する構成および管理ツール
  • を提供しています.
    ローカルで環境変数の設定方法
    Linux/Macのbashでは、コンフィギュレーションコードを追加する.bashrc、.bash_プロファイルまたは.profileなどのファイルの後ろに配置します.virtualenvを使用する場合は、virtualenvのbin/activateスクリプトに構成コードを追加して構成することもできます.
    構成コード:
    $ export SOME_SECRET_KEY=1c3-cr3am-15-yummy
    
    $ export AUDREY_FREEZER_KEY=y34h-r1ght-d0nt-t0uch-my-1c3-cr34m

    Winでは、cmd.exeではsetxコマンドで構成する、virtualenvのbin/activateでも良い.batスクリプトで構成します.
    構成コード:
    > set SOME_SECRET_KEY 1c3-cr3am-15-yummy

    PowerShell比cmd.exeはより強力で、Vistaおよび以上のバージョンで使用できます.PowerShellを使用して環境変数の設定を行います.
    現在のユーザーのみ:
    [Environment]::SetEnvironmentVariable("SOME_SECRET_KEY",
                                         "1c3-cr3am-15-yummy", "User")
    [Environment]::SetEnvironmentVariable("AUDREY_FREEZER_KEY",
                            "y34h-r1ght-d0nt-t0uch-my-1c3-cr34m", "User")

    本機の全ユーザーに対して:
    [Environment]::SetEnvironmentVariable("SOME_SECRET_KEY",
                                    "1c3-cr3am-15-yummy", "Machine")
    [Environment]::SetEnvironmentVariable("AUDREY_FREEZER_KEY",
                            "y34h-r1ght-d0nt-t0uch-my-1c3-cr34m", "Machine")

    本番環境での環境変数の構成例
  • Herokuに
  • を配置する.
    $ heroku config:set SOME_SECRET_KEY=1c3-cr3am-15-yummy
  • Pythonでこれらの構成情報
  • にアクセスする.
    >>> import os
    >>> os.environ["SOME_SECRET_KEY"]
    "1c3-cr3am-15-yummy"
  • settingsファイルにこれらの構成情報
  • がアクセスする.
    # Top of settings/production.py
    import os
    SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]

    SECRET未設定KEYの異常処理
    SECRET_がなければKEY値は、上のアクセスコードからKeyErrorが投げ出され、アイテムも起動できません.しかし、この例外は有効なプロンプト情報を提供しておらず、デバッグには不利です.
    settings/base.pyでは、次のコードを使用して処理します.
    # settings/base.py
    import os
    
    # Normally you should not import ANYTHING from Django directly
    # into your settings, but ImproperlyConfigured is an exception.
    from django.core.exceptions import ImproperlyConfigured
    
    def get_env_variable(var_name):
        """Get the environment variable or return exception."""
        try:
            return os.environ[var_name]
        except KeyError:
            error_msg = "Set the {} environment variable".format(var_name)
            raise ImproperlyConfigured(error_msg)

    次にsettingsファイルで次の操作を行います.
    SOME_SECRET_KEY = get_env_variable("SOME_SECRET_KEY")

    その後、SOME_が設定されていなければSECRET_KEYという環境変数では、以下のエラーメッセージが表示されます.
    django.core.exceptions.ImproperlyConfigured: Set the SOME_SECRET_KEY
    environment variable.
    manage.pyデフォルトDJANGO_SETTINGS_MODULEはsettingsを指す.py、マルチsettingsファイルではdjango-adminを使用することを推奨し、単一settingsファイルではmanage.pyを使用することを推奨します.この2つのコマンドは基本的に同等です.
    $ django-admin  [options]
    $ manage.py  [options]

    環境変数を設定できない場合
    Apacheなどは独自の環境変数を使用して、上記のシステムに対する環境変数の設定方法が無効である場合、機密情報を実行できないファイルに保存し、そのファイルのバージョン管理を行わないことができる.
  • 機密情報を保存するファイルを生成します.フォーマットはJSON、Config、YAMLまたはXMLです.
  • これらの情報を管理するためにloaderを追加する
  • .
  • は、ファイル名を増加する.gitignore和.hgignore

  • JSON形式の使用
  • secretsを生成する.jsonファイル:
  • {
        "FILENAME": "secrets.json",
        "SECRET_KEY": "I've got a secret!",
        "DATABASES_HOST": "127.0.0.1",
        "PORT": "5432"
    }
  • settings/base.pyにloaderを追加して、これらの情報にアクセスします:
  • # settings/base.py
    
    import json
    
    # Normally you should not import ANYTHING from Django directly
    # into your settings, but ImproperlyConfigured is an exception.
    from django.core.exceptions import ImproperlyConfigured
    
    # JSON-based secrets module
    with open("secrets.json") as f:
        secrets = json.loads(f.read())
    
    def get_secret(setting, secrets=secrets):
        """Get the secret variable or return explicit exception."""
        try:
            return secrets[setting]
        except KeyError:
            error_msg = "Set the {0} environment variable".format(setting)
            raise ImproperlyConfigured(error_msg)
    
    SECRET_KEY = get_secret("SECRET_KEY")

    複数のrequirementsファイルの使用
    各settingsファイルにはrequirementsファイルが対応し、異なる構成に対応して、対応する依存ファイルのみをインストールする必要があります.
    requirementsファイルの例:
    requirements/
        base.txt
        local.txt
        staging.txt
        production.txt

    base.txtには、次のようなグローバル依存が格納されます.
    Django==1.8.0
    psycopg2==2.6
    djangorestframework==3.1.1

    ローカル開発環境向けのlocal.txt、base.txtに加えて、他の依存度を追加します.
    -r base.txt # includes the base.txt requirements file
    
    coverage==3.7.1
    django-debug-toolbar==1.3.0

    継続的な統合サーバのci.txtは、以下のようにすることができる.
    -r base.txt # includes the base.txt requirements file
    
    coverage==3.7.1
    django-jenkins==0.16.4

    そしてtxtは基本的にbase.txtは同じです.
    -r base.txt # includes the base.txt requirements file

    インストール
    ローカル開発:
    $ pip install -r requirements/local.txt

    生産環境:
    $ pip install -r requirements/production.txt

    すべてのrequirementsファイルの依存パッケージは、プロジェクトがより安定していることを保証するために、特定のバージョンに指定されています.
    settingsファイルでのファイルパスの処理
    ファイルパスをハードコーディングしない
  • Unipathを用いるファイルパス処理
  • を行う.
    # At the top of settings/base.py
    from unipath import Path
    
    BASE_DIR = Path(__file__).ancestor(3)
    MEDIA_ROOT = BASE_DIR.child("media")
    STATIC_ROOT = BASE_DIR.child("static")
    STATICFILES_DIRS = (
        BASE_DIR.child("assets"),
    )
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            DIRS = (BASE_DIR.child("templates"),)
        },
    ]
  • はosを用いる.pathによるファイルパス処理
  • # At the top of settings/base.py
    from os.path import join, abspath, dirname
    
    here = lambda *dirs: join(abspath(dirname(__file__)), *dirs)
    BASE_DIR = here("..", "..")
    root = lambda *dirs: join(abspath(BASE_DIR), *dirs)
    
    # Configuring MEDIA_ROOT
    MEDIA_ROOT = root("media")
    
    # Configuring STATIC_ROOT
    STATIC_ROOT = root("collected_static")
    
    # Additional locations of static files
    STATICFILES_DIRS = (
        root("assets"),
    )
    
    # Configuring TEMPLATE_DIRS
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            DIRS = (root("templates"),)
        },
    ]

    プロファイルとDjangoのデフォルト構成の違いを見つけるには、Djangoのdiffsettingsコマンドを使用します.
    参考文献:
    Two Scoops of Django: Best Practices for Django 1.8