今回の内容
前回はDjangoの実践的なテストの書き方と、CircleCIを使った継続的インテグレーションについて解説しました。前回までのコードは以下から取得できます。
第4回となる今回は、まず環境変数について取り上げます。環境変数を用いたsettingsファイルの書き方を紹介した後は、Angularを使ってカンバンボードのUIを実装していきます。
環境変数
環境毎に異なる値としては、データベースの接続に必要な情報やTwitterなど外部サービスの認証情報等が思い浮かぶと思います。これらの設定を定数としてコード上で管理することはもちろん可能ですが、セキュリティと保守性の観点から推奨されません。「The Twelve-Factor App」の教えにのっとり、設定は環境変数から渡すようにしましょう。
「The Twelve-Factor App」とは、Heroku創業メンバーの一人が書いた、WebアプリケーションやSaaSを作り上げるための方法論です。日本語訳もあるので、ご存じない方はぜひ一度目を通してみてください。
Django-environ
Djangoで環境変数を扱うには、Django-environというサードパーティ製パッケージが便利です。Django-environは、.env
ファイルのサポートや簡潔なファイルパス指定といったメリットがあり、cookiecutter-djangoでも使われています。
それでは、Django-environをインストールします。
(env) $ pip install django-environ (env) $ vi requirements/base.txt (env) $ cat requirements/base.txt Django==2.0.2 django-environ==0.4.5 django-model-utils==3.1.1 djangorestframework==3.7.7
インストールが無事済んだら、config/settings/base.py
の先頭に以下のコードを追加しましょう。
import environ ROOT_DIR = environ.Path(__file__) - 3 # (modern-django/config/settings/base.py - 3 = modern-django/) 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')))
ここで記述したif文は、「環境変数でDJANGO_READ_ENV_FILE
をTrueに設定している場合のみ、.env
ファイルの値を読み込む」ということを意味しています。このおかげで開発環境での環境変数の管理が楽にできます。
また、environ.Path(__file__) - 3
のようにファイルパスの扱いが直感的にできるようになっているのもDjango-environの特徴のひとつです。
それでは次に、DEBUG
とSECRET_KEY
をそれぞれ環境変数から読み込むように修正してみましょう。現在のコードでは、SECRET_KEY
にはプロジェクト作成時にそれぞれ異なるランダムな文字列が、DEBUG
にはTrueが設定されています。それをDjango-environを利用して、以下のように書き直します。
# 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.bool('DEBUG', False)
DEBUG = env.bool('DEBUG', False)
は、変数DEBUG
がbool型であり、環境変数DEBUG
が設定されていない場合にはFalseがデフォルト値として使われるということを意味しています。env.bool()
がTrueとして評価する環境変数の値は以下の6パターンです(大文字と小文字は区別されません)。
- 'true'
- 'on'
- 'ok'
- 'y'
- 'yes'
- '1'
.env
ファイルも用意しておきましょう。リポジトリ直下に.env
ファイルを作成します。
(env) $ vi .env (env) $ cat .env DEBUG=True SECRET_KEY=<config/settings/base.pyに記述されていたランダムな文字列>
.env
ファイルには認証情報などを記載する場合もあるので、リポジトリにpushしないために.gitignore
に.env
を追加してください。
また.env
ファイルのひな型として、.env.example
ファイルを用意しておくことをお勧めします。.env.example
ファイルを用意することにより、.env
ファイルにどういった値を設定すればよいかわかりやすくなるだけでなく、.gitignore
に追加されている.env
ファイルの存在を見落とさなくなるメリットがあります。
(env) $ vi .env.example (env) $ cat .env.example DEBUG=True SECRET_KEY=your-secret-key
この状態で開発サーバーを起動すると、環境変数にSECRET_KEY
が見当たらないというエラー(KeyError
)が発生します。
(env) $ python manage.py runserver Traceback (most recent call last): File "/Users/massa142/src/github.com/massa142/modern-django/env/lib/python3.6/site-packages/environ/environ.py", line 273, in get_value value = self.ENVIRON[var] File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.py", line 669, in __getitem__ raise KeyError(key) from None KeyError: 'SECRET_KEY'
手元の環境で動かすためには、最後に環境変数DJANGO_READ_DOT_ENV_FILE
に値Trueをセットしましょう。これで先ほど用意した.env
ファイルの値が環境変数として読み込まれます。
(env) $ export DJANGO_READ_DOT_ENV_FILE=True (env) $ python manage.py runserver Performing system checks... System check identified no issues (0 silenced). January 08, 2019 - 08:39:30 Django version 2.0.2, using settings 'config.settings.local' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
継続的な開発をしていく際には、以下のように各自お使いのシェルにあわせて環境変数を設定しておくのがよいでしょう。
$ echo export DJANGO_READ_DOT_ENV_FILE=True >> ~/.bash_profile $ source ~/.bash_profile
Django-environにはまだ便利な機能が備わっています。例えば、適切に環境変数を登録しておくとenv.db()
でデータベースの設定を済ませることができます。Django-environについて他にも詳しく知りたい方は公式ドキュメントを参照してください。
設定ファイルの切り替え
第3回では環境毎に設定ファイルの切り替えを行う方法として、manage.pyコマンドの--settings
オプションを紹介しました。CircleCIの設定に記述されているpython -Wd manage.py test --settings=config.settings.base
というコードがその一例です。
--settings
オプションについての詳細は前回の記事を確認してください。
--settings
オプションを都度指定するのが面倒だと感じたり、環境毎にsettingsファイルを分割して管理するのは煩雑だという場合は、1つのsettingsファイルで管理するアプローチを検討しましょう。
ここまで説明してきた環境変数とif文を用いることによって、settings.py
ひとつで複数の環境に対応できます。
FeedHQというDjango製プロダクトのsettingsファイルの書き方が参考になるので、ぜひ確認してみてください。