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

# 概要
DjangoアプリをHerokuにデプロイした際の手順をまとめました。

**環境：**```python3.8.10```　```django3.2.6```

# 1.　Herokuにサインアップ・ログイン編
#### 1.1　Herokuにサインアップする
Heroku[公式サイト](https://jp.heroku.com)から、サインアップします。

#### 1.2　Herokuをインストールする
Heroku[公式サイト](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)から、お使いの環境に合ったものを選びHerokuをインストールします。
![スクリーンショット 2021-09-09 112055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1280658/396f1c5e-ca76-02d5-be2e-b49810b1af79.png)

#### 1.3　Herokuにログインする
PCでコマンドプロンプトを起動し、herokuにログインします。

```terminal
$ heroku login
```
ブラウザを立ち上げるために次のメッセージが表示される場合がありますので、適当なキー（Enterキーなど）を押下します。

```terminal
heroku: Press any key to open up the browser to login or q to exit: 
```

自動的にブラウザが立ち上がり、ログインボタンが出てくるので押下します。

# 2.　ファイル作成編
#### 2.1　仮想環境に入る
Djangoアプリのルートディレクトリに移動し、仮想環境に入ります。

```terminal
$ cd foo
$ Scripts\activate          #仮想環境に入る
```
#### 2.2　requirements.txtの作成
以下のコマンドで、requirements.txtを作成します。
```terminal
$ pip freeze > requirements.txt
```
#### 2.3　runtime.txtの作成
runtime.txtを作成します。```python-```の後に、使用しているpythonのバージョンを記載します。

```terminal
$ python --version                       #pythonのバージョンを確認するコマンド
$ echo python-3.8.10 > runtime.txt          
```
#### 2.4　Procfileの作成
以下のコマンドで、Procfileを作成します。
名前が違うとエラーが出てしまうので、必ず大文字Pから始まる「Procfile」としてください。
`settings.py`や`wsgi.py`と同じディレクトリに作成します。

```terminal
$ echo web: gunicorn ディレクトリ名.wsgi --log-file - > Procfile
```
#### 2.5　local_settings.pyの作成
次に`settings.py`のあるディレクトリに、`local_settings.py`を作成します。
```terminal
$ touch local_settings.py
```

#### 2.6　dj_database_urlをインストールする

```terminal
$ pip install dj-database-url
```
#### 2.7 django-herokuをインストールする
```terminal
$ pip install django-heroku
```

# 3.　ファイル編集編
#### 3.1 local_settings.pyを編集する

以下を`local_settings.py`に追加します。
`SECRET_KEY`は、`settings.py`からコピーして貼り付けてください。

```python:local_settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

SECRET_KEY = 'settings.pyからコピーしたSECRET_KEYをここに貼り付ける' 

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

DEBUG = True
```
また、`local_settings.py`を`.gitignore`でgitの管理から外します。

```terminal:.gitignore
myvenv
db.sqlite3
.DS_Store
local_settings.py         #追加する
```
#### 3.2　settings.pyを編集する

ローカルのDebugを`local_settings.py`で`True`にしたので、本番環境では`False`になるよう設定します。
```python:settings.py
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
```
ホストにHerokuを追加します。
```python:settings.py
ALLOWED_HOSTS = ['127.0.0.1' ,'herokuapp.com']
```

`MIDDLEWARE`に追加する`'whitenoise.middleware.WhiteNoiseMiddleware'`を追加します。位置に気を付けてください。

```python:settings.py
#CSSを反映させる
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
     #以下の行（whitenoise...）をdjango.middleware...の後、
     #django.contrib...よりも前に追加する
    'whitenoise.middleware.WhiteNoiseMiddleware',   
        
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
```
Staticファイルの設定を行います。
```python:settings.py
#CSSファイルの設定
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
```
`settings.py`の最後に、以下を追加します。最初にあったSECRET_KEYは削除します。
```python:settings.py
#Heroku database
import dj_database_url
db_from_env = dj_database_url.config()
DATABASES['default'].update(db_from_env)

db_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABASES['default'].update(db_from_env)

try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:
    SECRET_KEY = '***************************************'   // 削除したSECRET_KEYをコピペします
    import django_heroku
    django_heroku.settings(locals())
```
最終的にsettings.pyが以下のようになっていたらOKです。DATABASEは初期状態にします。
```python:settings.py
from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False  

ALLOWED_HOSTS = ['127.0.0.1' ,'herokuapp.com']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'your_app',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'coordinate_yohou.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'coordinate_yohou.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': '',
        'HOST': 'host',
        'PORT': '',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]



# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'


#Heroku database
import dj_database_url
db_from_env = dj_database_url.config()
DATABASES['default'].update(db_from_env)

db_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABASES['default'].update(db_from_env)

try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:
    SECRET_KEY = '**********************************************'
    import django_heroku
    django_heroku.settings(locals())
```

# 4.　デプロイ編
#### 4.1　git add、git commitする
以下のコマンドを実行して、Git管理をします。

```terminal
$ git add .
$ git commit -m "deploy heroku"
```

#### 4.2　Herokuのプロジェクトを作成する

```terminal
$ heroku create プロジェクト名
```
上記のコマンドが問題なく実行されると、以下のように終わります。

```termianl
creating プロジェクト名... done
```

#### 4.3 SECRET_KEYをHerokuに設定
```terminal
$ heroku config:set SECRET_KEY='settings.pyのSECRET_KEY'
```

#### 4.4　Herokuにプッシュする
```terminal
$ git push heroku master
```

#### 4.5　Dynoを起動させる
```terminal
$ heroku ps:scale web=1
```
### 4.6　データベースの設定
```createsuperuser```で作成したユーザー名・パスワードはメモしておきます。

```terminal
$ heroku run python manage.py migrate
$ heroku run python manage.py createsuperuser
```
### 4.7　アプリを開く
```terminal
$ heroku open
```

自動でブラウザが開き、Djangoアプリが表示されていたら成功です！！！


# 参考にしたサイト
https://tutorial-extensions.djangogirls.org/ja/heroku
https://devcenter.heroku.com/articles/getting-started-with-python#deploy-the-app