Nuxt&Django REST FrameworkでS3を使ってメディアを保存する


前提

画像ファイルや映像ファイルといったメディアを直接DBに保存するのはSQLのパフォーマンス的に現実的に考えるとなかなかあり得ることではありません。

やはりS3のようなストレージサービスに預けてそのパスをDRFで読み込み→クライアントサイドで出力が一般的でしょう。

なので今回はNuxtで画像を伴ったデータを追加し、それらがきちんと出力されるまでの流れを書いていきます。

なお、既にDjangoのプロジェクト、AWSのアカウントは所持しているものとします。

私はここからダウンロードしたコードの設定ファイルを変えて実装しています。

環境

boto3==1.13.25
botocore==1.16.25
Django==3.0.7
django-cors-headers==3.2.1
django-storages==1.9.1
djangorestframework==3.11.0

導入

IAM

まずはIAMにアクセスしてS3にアクセスができるようなユーザーを作っておきましょう。
AWSのマネジメントコンソールにアクセスした際に出てくる検索バーにIAMと打ち込み、IAMのページにアクセスしてください。

そこでユーザーのページからユーザーを追加するというというページにとび、そこで任意のユーザー名、プログラムによるアクセスにチェックを入れてアクセス権限のページへと進んでください。

そこでユーザーをグループに追加を選び、その上で任意のグループ名、そして権限としてAmazonS3FullAccessのポリシーを割り当てます。

これで次のタグの追加(オプション)に進みますが、ここは無視して確認に進んで大丈夫です。

すると新しく追加された場合、ユーザー名とアクセスキー、そしてシークレットアクセスキーが表示されます。

こちらはあとで使いますので覚えておいてください。
ここまででIAMに関する部分は終わりです。

S3

次にS3でデータの保存先となるバケットを作成しましょう。

S3にアクセスし、バケットを作成します。

今回はひとまずこういった設定にしました。
パブリックアクセスをオフにして、残りの設定はひとまず無視してこのまま作成して大丈夫です。

ここまででひとまずS3の初期設定は終わりです。

Django

DjangoでS3にファイルを保存するために、

をインストールします。

$ pip install boto3 django-storages

Settings
To upload your media files to S3 set:

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
To allow django-admin.py collectstatic to automatically put your static files in your bucket set the following in your settings.py:

STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

AWS_ACCESS_KEY_ID
Your Amazon Web Services access key, as a string.
AWS_SECRET_ACCESS_KEY
Your Amazon Web Services secret access key, as a string.

Note

If AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are not set, boto3 internally looks up IAM credentials.

AWS_STORAGE_BUCKET_NAME
Your Amazon Web Services storage bucket name, as a string.

どうやらドキュメントをみたところ、以下が必須なようです。

settings.py
# Django-Storage
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# AWS-Settings
AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID'
AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY'
AWS_STORAGE_BUCKET_NAME = 'nuxt-django'
AWS_LOCATION = 'static' # s3バケット上のベースとなるファイルパス

# STATIC-Files
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

こんな感じで設定しておいてください。

この後に

$ python manage.py collectstatic

を行うと・・・

164 static files copied.

といったようなメッセージが返ってきます。

実際にS3のバケットを見てみましょう。

実際にstaticというフォルダ名で保存されていますね。
ここまででひとまずDjangoの設定は終わりました。

DRFの設定

これが必要かと思いきや実は冒頭のソースをそのまま使った場合ここまでの設定だけで終わりです。
なので今後Nuxt側でAPIを叩いたらメディアファイルは自動的にS3にアップロードされます。

例えば、こういう風に、クライアントサイドから画像を伴ったPOSTを受けると・・・

こんな感じにアップロードされています。

ここまででひとまずメディアを保存することに成功したのでここで終わります。
お疲れ様でした。

この記事が誰かの役に立てば幸いです。