Django + Heroku + AWS S3で画像表示させる方法


概要

Djangoアプリで画像をS3に保存し、アプリに表示させる方法を書いてみます。

想定している処理は、①ユーザーが画像投稿②S3に保存③S3からアプリに画像表示です。

なお、環境はPython 3.7.3Django 2.2になります。


1. AWS設定


1-1. AWS登録

S3を使用するのに、AWSアカウントが必要になりますので、お持ちでない方はAWS Signupからご登録ください。

参照:

AWS アカウント作成の流れ

Amazon S3


1-2. バケット作成


①S3を検索してクリック

s3.png


②バケット作成

s3-02.png


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

s3-03.png


④オプションなし

オプションですが、今回は設定しません

s3-04.png


⑤アクセス権限

こちらの項目を外してください、初期設定ではブロックされてしまいます

s3-05.png


⑥内容を確認して作成

s3-06.png


⑦バケット完成

s3-07.png


1-3. CORS設定


①CORSの設定に移動

作成したバケットをクリックし、「アクセス制限」の「CORSの設定」に移動します

s3-08.png


②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>

参照:

Cross-Origin Resource Sharing (CORS)

Direct to S3 File Uploads in Python | S3 Setup


1-4. IAM設定


①IAMを検索してクリック

a.png


②ユーザーをクリック

b.png


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

c.png


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

d.png


⑤アクセス許可

S3を検索し、AmazonS3FullAccessにチェック

e.png


⑥オプションなし

オプションですが、今回は設定しません

f.png


⑦内容を確認して作成

g.png


⑧IAM設定完了

後ほど、アクセスキーIDシークレットアクセスキーを使いますので、画面を閉じないでください

i.png

参照:IAMとは


2. アプリ設定


2-1. インストール


①django-storagesインストール


terminal

$ pip install django-storages


参照:django-storages | Amazon S3


②boto3インストール


terminal

$ pip install boto3


参照:

Boto 3 Documentation

AWS SDK for Python (Boto3)


2-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.s3boto.S3BotoStorage'
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = S3_URL

AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None



2-3. 環境変数

Herokuの環境変数を3つ設定します。

①AWS_ACCESS_KEY_ID②AWS_SECRET_ACCESS_KEYは、IAMユーザーを追加した際に表示された、アクセスキーIDシークレットアクセスキーになります。

③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="ご自身のバケット名を記入"

参照:

Configuration and Config Vars | Heroku

Django Docs | Deployment checklist


2-4. requirements.txt

インストールしたモジュールをrequirements.txtに追加します。


terminal

$ pip freeze > requirements.txt



2-5. local_settings.py設定

もしlocal_settings.pyを使用している場合は、下記を参考にしてください。

ローカル環境ではMEDIA_ROOTで指定したディレクトリから読み込み、HerokuではS3から読み込むことができます。


settings.py

###

省略
###

DEBUG = False

ALLOWED_HOSTS = ['*']

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:
SECRET_KEY = os.environ['SECRET_KEY']

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.s3boto.S3BotoStorage'
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

SECRET_KEY = 'ご自身のSECRET_KEYを記入'

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

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

DEBUG = True



最後に

Herokuでのデプロイが曖昧でしたら、下記の記事も参考にしてみてください。

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

以上