5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Django】Djangoで静的ファイルをS3に保存する一番簡単な方法【AWS S3】

Last updated at Posted at 2021-09-01

Djangoで静的ファイルをS3に保存する一番簡単な方法

調べたらカスタムストレージクラスを作る方法がいろいろ出てきたけど意味不明だったので自分用に。
多分これが一番簡単だと思います。

【参考】

pyをいじっていく

1. models.py , forms.py

一般的な方法でPhotoモデル,Photoformモデルを作成する
自分はDjnagoBrosというサイトで紹介されている写真投稿サイトを作って、それを改造する形で実装しました。

2. project_name/urls.py

本番環境想定の設定にしてみる

if settings.DEBUG:
    urlpatterns += static(
        settings.MEDIA_URL, document_root=settings.MEDIA_ROOT
    )
  • settings.py の DEBUG が True の場合だけ Local に保存されるように設定

必要ライブラリをインストールする

S3にアップするにはやはりAWSと連携するライブラリを使う必要がある
しっかり用意されてるので、それを使ってく
※pyenvを使っている場合、仮想環境に入っておくことを忘れないように

$ pip install boto3
$ pip install django-storages

S3にバケットを作成する

コンソールで作成

  • バケットポリシー
    ポリシーはdjango-storageのUsageにあるものをコピーしてくる
    AWSIDやバケット名は自分のやつに変える
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AWS_ACCOUNT_ID:user/bucket_name"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::bucket_name/*",
                "arn:aws:s3:::bucket_name"
            ]
        }
    ]
}

IAM ユーザ作成

S3の操作権限を持つIAMユーザを作る

  • 名前 : なんでもいいです
  • プログラムによるアクセス
  • S3FullAccess (めんどくさいので) (絞る場合、↑のポリシーで指定したものだけ入れたらOK)
  • 認証情報 : DLしてローカルPCにでも保存しておきます

settings.py 編集

  • DEBUGモード解除
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False # Falseにする

ALLOWED_HOSTS = ["127.0.0.1", "xxx.xxx.xxx.xxx"] # DEBUG = False の時は指定しないと起動できない
# この辺はまだよくわかってないので今回はとりあえず127.0.0.1を許可しておく
  • INSTALLED_APPS に 'storages' 追加

pip でインストールしておいたdjango-storageを使うために必要

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_cleanup',
    'app',
    'storages', # 追加
]
  • static設定
# STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

# Media files
# MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# EDIA_URL = '/media/'

# staticファイルの参照先
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# mediaファイル保存先
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
  • STATICFILES_DIRS : プロジェクトのアプリで使うstaticファイルを格納している、サーバ内の場所を指定する (今回は project_name/static)

  • STATICFILES_STORAGE : CSSなどを参照するstaticファイルの保管先を指定

  • DEFAULT_FILE_STORAGE : 投稿機能によってアップロードされた写真の保管先を指定

  • 'storages.backends.s3boto3.S3Boto3Storage' を指定することで↓のS3設定を参照するようになる

  • 元のmedia設定は不要なのでコメントアウトか、消しておく

  • S3設定

# アクセスキーID
AWS_ACCESS_KEY_ID = 'AKIA**************'
# シークレットアクセスキー
AWS_SECRET_ACCESS_KEY = '*************************'
# バケット名
AWS_STORAGE_BUCKET_NAME = 'bucket_name'
# 保存先URL
STATIC_URL = 'https://%s.s3.ap-northeast-1.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
AWS_LOCATION = 'static'
  • AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY : IAM作成時にDLしてきた認証情報を入力する
  • AWS_STORAGE_BUCKET_NAME : さっき作ったバケット名を入力する
  • STATIC_URL : バケットのURLを入力する
    • 適当にファイルおいて、AWSコンソールでそのファイルの詳細の「オブジェクトURL」を見たらわかる
  • AWS_LOCATION : static関係のファイルをコピーする際、バケット内にディレクトリを作りたい場合指定
    • 今回は bucket_name/static/静的ファイル という構造にしたいので、'static' を入力

必須項目は以上。 他にもいろいろ指定できるけど、とりあえず↑だけでよさそう

collectstatic 実行

このままだとdjangoがstaticを認識できないので、collectstaticをいうコマンドを使ってstaticファイルを同期する

プロジェクトのディレクトリ上で
$ python manage.py collectstatic

You have requested to collect static files at the destination
location as specified in your settings.

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes ← yesを入力

129 static files copied.

collectstaticがうまくいって、S3のバケットに static ディレクトリ、その中に admin , css ディレクトリができていればOK!

画像のS3アップロード確認

runnserver して 実際に画像を投稿してみる
→S3の static ディレクトリの中に photos/ が作成されて、その中に実際の画像ファイルが保存されていればOK!

画像保存先のディレクトリ名はモデルで指定↓

models.py
class Photo(models.Model):
    title = models.CharField(max_length=150)
    comment = models.TextField(blank=True)
    image = models.ImageField(upload_to='photos') # ←これ
    category = models.ForeignKey(Category, on_delete=models.PROTECT)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title
5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?