django-storages-s3 について
django-storagesとboto3を使い、AWS S3の本番向けファイルストレージを設定・監査するDjango向けスキルです。静的・メディアファイル、公私のバックエンド、署名付きURL、実際のS3に接続しないテストを扱います。
主な機能
- 01Django STORAGESのS3設定
- 02静的ファイルとメディアの分離
- 03公開・非公開バックエンドの設定
- 04署名付きURLの生成
- 05テストでのS3モック
- 06IAMとストレージ設定の監査
活用シーン
- 01Djangoのアップロード先をローカルからS3へ移行
- 02CloudFront経由で静的ファイルを配信
- 03非公開のダウンロード・アップロードリンクを提供
- 04S3に接続せずストレージ動作をテスト
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jeffallan/ claude-skills --skill django-storages-s3インストール後、Claude Code で/django-storages-s3を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/configuration.mdcustom-backends.mdpresigned-urls.mdtesting-storages.md詳細
Django Storages S3
django-storages と boto3 を使って AWS S3 上で本番環境に適したファイルストレージを実現する、Django のシニアスペシャリストです。公開・非公開メディア、静的ファイル、署名付き URL、CloudFront に対応します。
このスキルを使用する場面
- ローカルファイルシステムの代わりに、AWS S3 から静的ファイルやメディアファイルを配信する場合
- Django 4.2 以降の
STORAGESdict、または従来のDEFAULT_FILE_STORAGEを設定する場合 - 公開(CDN 配信)用と非公開(署名付き)用のファイルバックエンドを分ける場合
- 署名付きのダウンロード URL、またはブラウザーから S3 に直接アップロードする URL を生成する場合
- S3 の前段に CloudFront を配置し、最小権限の IAM ポリシーを作成する場合
- コードを変更せずに、ローカルの
FileField/ImageFieldストレージを S3 に移行する場合 - S3 に接続せずにストレージコードをテストする場合
基本的なワークフロー
- インストールと登録 —
pip install django-storages[s3] boto3を実行し、"storages"をINSTALLED_APPSに追加します - 認証情報の設定 — 環境変数から読み込むか、アタッチされた IAM ロールを使用します。ハードコードは避けてください
STORAGESdict の設定 —default(メディア)とstaticfilesのバックエンドを設定し、それぞれ異なるlocationプレフィックスを指定します- 名前付きバックエンドの追加 — 必要に応じて、
STORAGESのエントリを追加し、公開用と非公開用のバケット/ACL を分けます - 確認とテスト —
collectstaticを実行してアップロードが S3 に保存されることを確認し、テストではInMemoryStorageまたはmotoで S3 をモックします
リファレンスガイド
状況に応じて詳細なガイダンスを参照してください。
| トピック | リファレンス | 参照するタイミング |
|---|---|---|
| 設定と STORAGES | references/configuration.md | 基本設定、4.2 以降と従来方式の違い、CloudFront |
| カスタムバックエンド | references/custom-backends.md | 公開/非公開バケット、フィールドごとのストレージ |
| 署名付き URL | references/presigned-urls.md | ダウンロードリンク、ブラウザーからの直接アップロード |
| テストと IAM | references/testing-storages.md | S3 のモック、IAM ポリシー、よくある落とし穴 |
最小限の動作例
以下のスニペットでは、必ず守るべき基本要件を示します。環境変数からの認証情報の読み込み、STORAGES dict、メディアと静的ファイルで異なる保存先、メディアバックエンドでの default_acl=None です。
# settings.py
import os
AWS_STORAGE_BUCKET_NAME = os.environ["AWS_STORAGE_BUCKET_NAME"]
AWS_S3_REGION_NAME = os.environ.get("AWS_S3_REGION_NAME", "us-east-1")
AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_S3_REGION_NAME}.amazonaws.com"
# On EC2/ECS/Lambda, omit keys entirely — boto3 uses the attached IAM role.
STORAGES = {
"default": { # media uploads
"BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
"OPTIONS": {
"bucket_name": AWS_STORAGE_BUCKET_NAME,
"location": "media",
"default_acl": None, # rely on bucket policy, not per-object ACLs
"file_overwrite": False,
"querystring_auth": False, # public objects → clean URLs
},
},
"staticfiles": {
"BACKEND": "storages.backends.s3boto3.S3StaticStorage",
"OPTIONS": {
"bucket_name": AWS_STORAGE_BUCKET_NAME,
"location": "static",
},
},
}
MEDIA_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/media/"
STATIC_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/static/"
# models.py — uploads go straight to S3 on save()
from django.db import models
class Document(models.Model):
file = models.FileField(upload_to="docs/") # uses STORAGES["default"]
既存の設定の監査
すでに S3 を使用しているプロジェクトを確認する場合(新規構築ではない場合)は、以下のチェックリストに沿って確認してください。各項目は、以下の制約を「X を探し、Y を確認する」という形で言い換えたものです。
- 認証情報 —
grep -rn "AWS_SECRET_ACCESS_KEY\|aws_secret" settings/→ 値がos.environ/django-environまたは IAM ロールから取得され、リポジトリにコミットされたリテラルではないことを確認します。 - ACL —
grep -rn "default_acl\|AWS_DEFAULT_ACL" .→ 2023 年 4 月以降に作成されたバケットでは、すべての値がNoneである必要があります。"public-read"/"private"のいずれかを指定するとAccessControlListNotSupportedが発生します。公開アクセスはバケットポリシーで設定します。 - ストレージバックエンド — Django 4.2 以降では、
DEFAULT_FILE_STORAGE/STATICFILES_STORAGEではなくSTORAGESdict を使用していることを確認します(これらの設定は Django 5.1 で削除されているため、5.1/5.2/6.0 では無視されます)。また、静的ファイル用クラスが架空の名前ではなくS3StaticStorageであることを確認します。 - 保存先 —
default(メディア)とstaticfilesに異なるlocationプレフィックスまたはバケットが設定され、collectstaticとアップロードが競合しないことを確認します。 - リージョン —
region_name(またはグローバル設定のAWS_S3_REGION_NAME)がバケットの実際のリージョンと一致し、us-east-1以外のバケットではAWS_S3_CUSTOM_DOMAINにリージョンのセグメントが含まれていることを確認します。 - 署名付き URL — 非公開バックエンドでは
querystring_auth=Trueかつcustom_domain=Noneであることを確認します。また、署名付き.url()の結果がAWS_QUERYSTRING_EXPIREの期限を超えてキャッシュされないことを確認します。 - 上書き時のクリーンアップ —
file_overwrite=Falseの場合、置き換えられたファイルが明示的に削除されることを確認します(削除されないと、古いオブジェクトが残ります)。 - IAM — ポリシーで許可されているのがバケット ARN に対する
Get/Put/Delete/ListBucketのみであり、より広範な S3 アクセスが付与されていないことを確認します。
制約
必ず行うこと
- AWS の認証情報は、環境変数またはアタッチされた IAM ロールから読み込みます
- バケットポリシー(オブジェクト ACL ではありません)でアクセスを制御できるよう、
default_acl=Noneを設定します - 静的ファイルとメディアファイルには、別々の
locationプレフィックスまたは別々のバケットを使用します - Django 4.2 以降では
STORAGES辞書を使用します(5.2 LTS および 6.0 でも同じ設定を使用できます)。DEFAULT_FILE_STORAGE/STATICFILES_STORAGEは 5.1 で削除されたため、4.2 未満でのみ使用します - 署名付き URL を発行するバックエンドには、
custom_domain=Noneを設定します - テストでは実際のバケットに接続せず、S3 をモックします(
InMemoryStorageまたはmotoを使用します)
絶対に行わないこと
AWS_SECRET_ACCESS_KEYをsettings.pyにハードコードしたり、コミットしたりしないでくださいquerystring_auth=Trueとcustom_domainを併用しないでください(署名付き URL の生成に失敗します)- 静的ファイルとメディアファイルを同じプレフィックスに混在させないでください
- IAM ユーザーに、バケット ARN に対する
Get/Put/Delete/ListBucketより広い権限を付与しないでください - 2023 年 4 月以降に作成されたバケットで、オブジェクトごとの ACL に依存しないでください(ACL はデフォルトで無効です)
ナレッジリファレンス
django-storages、S3Boto3Storage、S3StaticStorage、boto3、STORAGES 辞書、署名付き URL、generate_presigned_post、CloudFront、IAM ポリシー、InMemoryStorage、moto
関連スキル
django-expert— このスキルが S3 に永続化するファイルを生成する、Django のコアモデル、DRF、ORMfullstack-guardian— 保存されたファイルの安全なエンドツーエンドのアップロードフローとアクセス制御devops-engineer— このスキルが対象とする S3 バケット、IAM ロール、CloudFront ディストリビューションのプロビジョニング
コメント
Markdown 対応