HerokuにDjangoアプリをデプロイする方法

## はじめに
Djangoで作っていたアプリを、Herokuで動かしたいと思ったときに躓いたのでそのメモ。

## 前提

- gitはインストール済
- Herokuアカウント作成済
- HerokuCLIインストール済
- デプロイしたいDjangoアプリは完成している

## パッケージのインストール
#### django-toolbelt

```
pip install django-toolbelt
```
詳細は→[こちら](https://pypi.org/project/django-toolbelt/)

これをインストールすることで下記パッケージがインストールされる。

- Django
    - Django本体 
- psycopg2
    - PythonでpostgreSQLを扱いやすくする
- gunicorn
    - HerokuでDjangoをデプロイするときに推奨されている、Webサーバー
- dj-database-url
- dj-static

#### whitenoise

```
pip install whitenoise
```
WSGIアプリケーションのための静的ファイルを配信するのを簡単にしてくれるライブラリ。

## Djangoプロジェクトの修正
Herokuにデプロイするためには下記ファイルを追加・修正をしなければならない。

- requirements.txt
    - アプリを動かすために必要なパッケージを一覧としてまとめておくファイル
- Procfile
    - Herokuプロセスの起動コマンド
- runtime.txt
    - 使用するPythonのバージョンを指定
- .gitignore
    - sqliteとかが一緒に入らないようにする
- wsgi.py
    - setting.pyから環境変数を受け取ってDjangoを動かしている...らしい
 
#### requirements.txtの作成について
下記でファイルを作成できる

```
pip freeze > requirements.txt
```

ファイルの中身は下記のような感じになっている。

```
dj-database-url==0.5.0
Django==2.2.3
django-toolbelt==0.0.1
gunicorn==19.9.0
```

#### Procfile(例)

```
web: gunicorn <your-project-name>.wsgi --log-file -
```

#### runtime.txt(例)
```
python-3.6.1
```

#### .gitignore

```
*.pyc
venv
staticfiles
db.sqlite3
```

#### wsgi.py

```python:wsgi.py
import os

from dj_static import Cling
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_project_name.settings")

application = Cling(get_wsgi_application())
```


作成したファイルは下記の位置に配置する。

```
├─django_project_name
   │  db.sqlite3
   │  manage.py
   │  Procfile　☆
   │  requirements.txt　☆
   │  runtime.txt　☆
   │  .gitignore　☆
   │  
   ├─django_app_name
   │    admin.py
   │    apps.py
   │    forms.py
   │    models.py
   │    tests.py
   │    urls.py
   │    views.py
   │    __init__.py
   │          
   └─django_project_name
         settings.py
         urls.py
         wsgi.py ☆
         __init__.py
```

## Django設定ファイルの修正
次に、設定ファイル「settings.py」を修正する。

#### DB周りの設定
HerokuではDBはpostgresを使用する(SQLiteは使えない？)。そのため、動作環境によって使用するDBの設定を変えなければならない。
また、DEBUG=Falseにもしておく。

書き方は下記の方を参考にさせていただきました。
- [Django2.0でHerokuデプロイ手順](https://qiita.com/RyuSA/items/04f8f6a22370ca639ff9)

```python:settings.py
# hostnameが自分のpcの場合は、sqliteに接続する
# そうでない場合はherokuのpostgresに接続する
from socket import gethostname
hostname = gethostname()
if "myhostname" in hostname:
    DATABASES = {
       'default': {
           'ENGINE': 'django.db.backends.sqlite3',
           'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
       }
    }
    ALLOWED_HOSTS = []
else:
    # 本番環境ではデバッグモードはfalseにしておく
    DEBUG = False
    import dj_database_url
    db_from_env = dj_database_url.config()
    DATABASES = {
        'default': dj_database_url.config()
    }
    ALLOWED_HOSTS = ['*']
```


#### 静的ファイルの設定について
DEBUGをfalseにすると、CSSなどの静的ファイルが適用されていない。
HerokuやWebサーバーにデプロイするときは静的ファイルの置き場所を一か所にまとめる必要がある。
まず、settings.pyにどこに集めるかなどの設定を記述する。

```python:settings.py
import os

# settingsファイルのパスが入る
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# manage.pyのcollectstaticをした時に、静的ファイルがどこに格納されるか指定する
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

# HerokuやWebサーバーに静的ファイルを見に行く場所を指定する
STATIC_URL = '/static/'

# 各アプリケーションのstatic以外に配信するディレクトリがある場合に追加
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, '..', 'django_app_name', 'static'),
)
```

また、インストールしたwhitenoiseの設定を行う
MIDDLEWAREについては'django.middleware.security.SecurityMiddleware'の後ろに追加する。

```python:settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', ☆追加部分
    'django.contrib.sessions.middleware.SessionMiddleware',
    ...
]

STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'

```

上記の追記後、下記コマンドを実行する

```
python manage.py collectstatic
```

すると、指定した場所にstaticフォルダが作成され、静的ファイルが集められている。

```
├─django_project_name
   │  db.sqlite3
   │  manage.py
   │  Procfile
   │  requirements.txt
   │  runtime.txt
   │  
   ├─django_app_name
   │    admin.py
   │    apps.py
   │    forms.py
   │    models.py
   │    tests.py
   │    urls.py
   │    views.py
   │    __init__.py
   │          
   └─django_project_name
         static ☆
         settings.py
         urls.py
         wsgi.py
         __init__.py
```

## Herokuにデプロイ
下記は準備できているものとし、ここでは取り上げません。

1. Herokuアカウント  
2. Git
[こちら](https://git-scm.com/book/ja/v2)を参考に
3. Heroku Command Line Interface 
[こちら](https://devcenter.heroku.com/articles/getting-started-with-python#set-up)から

まずはコミットしておく

```
$ cd django_project_name
$ git init
$ git add .
$ git commit -m "はじめてのコミット"
```

HerokuCLIをインストールすると、Herokuコマンドが使えるようになる。
Herokuアカウントを作った際の情報で下記コマンドでログインする。

```
$ heroku login
```

次に、デプロイしたいアプリケーションの改装に移動し、下記コマンドを打つ

```
$ heroku create
> Heroku上にアプリを作成する。

$ git push heroku master
> Heroku上にソースコードを渡す。

$ heroku run python manage.py migrate
> ここでもmigrateをしてあげる

$ heroku ps:scale web=1

$ heroku open
```

## 完了！！
以上で、デプロイされているはず。