Django Heroku S3(AWS) 画像表示

#前提
画像をS3に保存し、本番環境で画像を表示させる方法をメモします。

DjangoアプリケーションをHerokuにデプロイ済み。
AWSアカウント設定済み。

環境
python-3.7.6
Django 2.2

##AWS設定
AWS登録をS3を使用するのに、AWSアカウントが必要になります。

###1、バケット作成
①S3を検索してクリック

②バケット作成

③バケット名とリージョンを選択

④オプションなし

⑤アクセス権限設定

⑥内容を確認して作成

⑦バケット完成

###２、CORS設定
①CORSの設定に移動
作成したバケットをクリックして、<code>アクセス制限</code>の<code>CORSの設定</code>に移動します

②CORS構成エディターに追加
以下を記入。

```

CORS
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

```

###３、IAM設定
①IAMを検索してクリック

②ユーザーをクリック

③ユーザー追加をクリック

④ユーザー名を入力、プログラムによるアクセスをチェック

⑤アクセス許可
S3を検索し、AmazonS3FullAccessにチェック

⑥オプションなし

⑦内容を確認して作成

⑧IAM設定完了
アクセスキーIDとシークレットアクセスキーを使うため、画面を閉じないでそのままにするか、どこかにメモしときます。


##アプリ設定
###1、インストール
①django-storagesインストール

```terminal.
$ pipenv install django-storages
```

②boto3インストール

```terminal.
$ pipenv install boto3
```

###2、settings.py設定
下記のように追加してください

```settings.py
    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'your_app_name',
    'storages', #追記
]

    #ここより下も追記
    AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
    AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
    AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']

    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
    MEDIA_URL = S3_URL

    AWS_S3_FILE_OVERWRITE = False
    AWS_DEFAULT_ACL = None
```


###3、環境変数
続いてHeroku側での環境変数を3つ設定します。
ここでIAMユーザーを追加した際に表示された、アクセスキーIDとシークレットアクセスキーを入力していきます。

①AWS_ACCESS_KEY_ID　　　　←IAMユーザーを追加した際に表示された、アクセスキーID
②AWS_SECRET_ACCESS_KEY　　←シークレットアクセスキー
③AWS_STORAGE_BUCKET_NAME　←作成したバケット名

```terminal.
$ heroku config:set AWS_ACCESS_KEY_ID="ご自身のアクセスキーIDを記入"
$ heroku config:set AWS_SECRET_ACCESS_KEY="ご自身のシークレットアクセスキーを記入"
$ heroku config:set AWS_STORAGE_BUCKET_NAME="ご自身のバケット名を記入"
```

###4、requirements.txt
インストールしたモジュールをrequirements.txtに追記していきます。

```terminal.
$ pipenv lock -r > requirements.txt
```

###5、local_settings.py設定
下記の記述でローカル環境ではMEDIA_ROOTで指定したディレクトリから読み込み、
HerokuではS3から読み込むことができます。

```settings.py

#省略

DEBUG = False

ALLOWED_HOSTS = ['herokuアプリ名']

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

#省略

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:

    AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
    AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
    AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']

    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
    MEDIA_URL = S3_URL

    AWS_S3_FILE_OVERWRITE = False
    AWS_DEFAULT_ACL = None

    import django_heroku
    django_heroku.settings(locals())

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

#省略

DEBUG = True
```

以上で画像をアップロードしてみて、S3に画像がアップロードされていれば完了です。