setting.pyの設定値を開発環境に合わせて切り替える

# 概要
DjangoでSQLite以外を使用する際、settings.pyにDB接続情報が含まれるため、Githubにて管理する場合は注意が必要となる。
また開発環境によっては接続先が変わるため、接続先ごとにsettings.pyを作成するのは手間となる。
接続先以外に変更が生じた場合は全ファイルを更新しなけれなならない。

色々と調べてみると、`django-environ`というライブラリを発見した。
Django起動時にDB接続先などの設定値をシステム環境変数に格納し、settings.pyのロード時に格納したシステム環境変数をALLOWED_HOSTSなどのフィールドにセットすることができる。
settings.pyの管理のわずらわしさを解消するために作成されたようなライブラリである。
[公式サイト](https://pypi.org/project/django-environ/)もよいが、下記のサイトが大変わかりやすかったので、`django-environ`を導入する手順をまとめる。

[引用：django-environで環境変数を管理してみる](https://e-tec-memo.herokuapp.com/article/172/)

# 導入方法

1. ライブラリのインストール
1. 環境変数定義ファイルの作成
1. settings.pyに組み込む

## 手順１

ライブラリ`django-environ`を`pip`でインストールするだけ。

```
pip install django-environ
```

## 手順２

環境変数定義ファイルを作成する。ファイル名は`.env`とし、**manage.pyと同じディレクトリ**に作成すること。
manage.pyと同じディレクトリに作成する理由は手順３で後述

```
djnago project
├── manage.py
├── .env
└── xxxx
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```
.envファイルにはALLOWED_HOSTSやDATABASESなど、settings.pyで定義していたシステム固有の情報をkey=valueの形式で定義する。
SQLite以外のDBを使用する際、DATABASESにユーザー名やパスワードの設定がそれぞれ必要となるが、DATABASE_URLで記載すると1行で書ける。
ALLOWED_HOSTSにホスト名を複数定義する場合はカンマ区切りとする。
下記では開発環境と本番環境を切り替えるために必要な項目を定義している。

```.env
SECRET_KEY=aiueo
DEBUG=True
ALLOWED_HOSTS=
DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/NAME
```

### DATABASE_URL一覧

各データベースでのDATABASE_URLの記載方法は下記の通り。

|Engine|Django Backend|URL|
|---|---|---|
|PostgreSQL|django.db.backends.postgresql_psycopg2|postgres://USER:PASSWORD@HOST:PORT/NAME|
|PostGIS|django.contrib.gis.db.backends.postgis|postgis://USER:PASSWORD@HOST:PORT/NAME|
|MSSQL|sql_server.pyodbc|mssql://USER:PASSWORD@HOST:PORT/NAME|
|MySQL|django.db.backends.mysql|mysql://USER:PASSWORD@HOST:PORT/NAME|
|MySQL (GIS)|django.contrib.gis.db.backends.mysql|mysqlgis://USER:PASSWORD@HOST:PORT/NAME|
|SQLite|django.db.backends.sqlite3|sqlite:///PATH|
|SpatiaLite|django.contrib.gis.db.backends.spatialite|spatialite:///PATH|
|Oracle|django.db.backends.oracle|oracle://USER:PASSWORD@HOST:PORT/NAME|
|Oracle (GIS)|django.contrib.gis.db.backends.oracle|oraclegis://USER:PASSWORD@HOST:PORT/NAME|
|Redshift|django_redshift_backend|redshift://USER:PASSWORD@HOST:PORT/NAME|

## 手順３
### .envファイルの読み込み

.envファイルの設定情報をsettings.pyで読み込む。
下記ではBASE_DIRにある.envファイルを読み込んでいる。
.envファイルをmanage.pyと異なるディレクトリに配置する場合は、ディレクトリの指定が必要となる。

```settings.py
import environ

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

env = environ.Env(DEBUG=(bool,True))
env.read_env(os.path.join(BASE_DIR,'.env'))
```
### 各フィールドへの設定方法

あとは取得したいキー名を指定して、.envファイルの設定値を取得するだけ。
設定値はEnvクラス内で保持されており、辞書型で参照できる。
存在しないキーを指定した場合はKeyErrorが発生するので注意。この辺りは`os.environ`と同じ仕様。

`get_value`という関数で取得することもできる。`get_value`ではキーが存在しない場合でもKeyErrorが発生せず、戻り値を引数に指定できる。戻り値の型も指定できる。

```
Env.get_value(var, cast=None, default=NOTSET, parse_default=False) -> float
```
ALLOWED_HOSTSは複数のホスト名が定義されることを踏まえて、list型を返す関数を使用している。
DATABASESの'default'にはDBに接続するユーザー名やパスワード等を個別に定義していたが、`.db()`の関数を使用すると、DATABASE_URLの内容を'default'で読めるlist型に変換してくれるので、とても便利。

```settings.py
SECRET_KEY = env.get_value('SECRET_KEY',str)

DEBUG = env.get_value('DEBUG', bool)

ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')

SESSION_COOKIE_AGE = env.get_value('SESSION_COOKIE_AGE', int) # セッション有効期間（秒）

DATABASES = {
    'default':env.db(),
}
```

# まとめ

* `django-environ`を使うとsettings.pyの管理コストが軽減できる。
* 開発環境の切り替えは`.env`ファイルの設定値を切り替えるだけ。