mcpField
D
django-storages-s3

django-storages-s3

github.com/farmage云与 DevOps21856 次安装5 周前更新
代码仓库

关于 django-storages-s3

这是一项 Django 开发技能,帮助使用 `django-storages` 和 `boto3` 配置并审查生产环境的 AWS S3 文件存储。内容涵盖公开与私有媒体、静态文件、预签名 URL、CloudFront、IAM 权限边界,以及不访问 S3 的测试方法。

主要功能

  1. 01配置 Django 的 S3 存储后端
  2. 02分离静态文件和媒体文件
  3. 03设置公开与私有存储
  4. 04指导预签名下载和上传
  5. 05检查凭据、ACL 和 IAM 策略
  6. 06无需连接真实 S3 即可测试存储代码

适用场景

  1. 01将 Django 上传文件从本地迁移到 S3
  2. 02将静态资源和媒体存放在不同位置
  3. 03构建私有下载或直接上传流程
  4. 04审查现有 S3 存储配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/farmage/opencode-skills --skill django-storages-s3

安装后在 Claude Code 中输入/django-storages-s3确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
configuration.md
custom-backends.md
presigned-urls.md
testing-storages.md

详细介绍

Django Storages S3

专注于 Django 的高级工程师,擅长通过 django-storages 和 boto3 在 AWS S3 上构建生产级文件存储——包括公开和私有媒体文件、静态文件、预签名 URL 以及 CloudFront。

何时使用此技能

  • 从 AWS S3 而非本地文件系统提供静态文件和/或媒体文件
  • 配置 Django 4.2+ 的 STORAGES 字典或旧版 DEFAULT_FILE_STORAGE
  • 分离公开(由 CDN 提供服务)和私有(使用预签名 URL)文件后端
  • 生成预签名下载 URL,或生成供浏览器直接上传到 S3 的 URL
  • 在 S3 前置 CloudFront,并编写遵循最小权限原则的 IAM 策略
  • 将本地 FileField/ImageField 存储迁移到 S3,无需更改代码
  • 在不访问 S3 的情况下测试存储代码

核心工作流

  1. 安装并注册 — pip install django-storages[s3] boto3;将 "storages" 添加到 INSTALLED_APPS
  2. 配置凭据 — 从环境变量加载凭据,或使用已附加的 IAM 角色;切勿硬编码
  3. 配置 STORAGES 字典 — 为 default(媒体文件)和 staticfiles 后端设置不同的 location 前缀
  4. 添加命名后端 — 有需要时,将公开与私有存储桶/ACL 拆分为额外的 STORAGES 条目
  5. 验证并测试 — 运行 collectstatic,确认上传的文件进入 S3,并在测试中使用 InMemoryStorage 或 moto 模拟 S3

参考指南

根据上下文加载详细指南:

主题参考文档适用场景
设置与 STORAGESreferences/configuration.md核心设置、4.2+ 与旧版对比、CloudFront
自定义后端references/custom-backends.md公开与私有存储桶、按字段配置存储
预签名 URLreferences/presigned-urls.md下载链接、浏览器直接上传
测试与 IAMreferences/testing-storages.md模拟 S3、IAM 策略、常见问题

最小可用示例

以下代码片段展示了核心 MUST DO 约束:从环境变量加载凭据、使用 STORAGES 字典、分开配置媒体/静态文件位置,以及在媒体后端设置 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”:

  1. 凭据 — grep -rn "AWS_SECRET_ACCESS_KEY\|aws_secret" settings/ → 确认值来自 os.environ/django-environ 或 IAM 角色,而不是提交到代码仓库中的字面值。
  2. ACL — grep -rn "default_acl\|AWS_DEFAULT_ACL" . → 对于 2023 年 4 月之后创建的存储桶,所有值都必须为 None。任何 "public-read"/"private" 都会引发 AccessControlListNotSupported;公开访问应通过存储桶策略配置。
  3. 存储后端 — 确认 Django 4.2+ 使用 STORAGES 字典,而不是 DEFAULT_FILE_STORAGE/STATICFILES_STORAGE(这些设置已在 Django 5.1 中移除,因此在 5.1/5.2/6.0 中会被静默忽略);确认静态文件类是 S3StaticStorage,而不是凭空编造的名称。
  4. 位置 — 确认 default(媒体文件)和 staticfiles 使用不同的 location 前缀或存储桶,避免 collectstatic 与上传文件发生冲突。
  5. 区域 — 确认 region_name(或全局设置 AWS_S3_REGION_NAME)与存储桶的实际区域一致,并确认对于非 us-east-1 存储桶,AWS_S3_CUSTOM_DOMAIN 包含区域段。
  6. 预签名 — 对于私有后端,确认 querystring_auth=True 且 custom_domain=None;确认预签名 .url() 的结果不会在 AWS_QUERYSTRING_EXPIRE 之后继续缓存。
  7. 覆盖清理 — 若设置了 file_overwrite=False,确认替换文件时会显式删除旧文件(否则被取代的对象会一直残留)。
  8. IAM — 确认策略仅对存储桶 ARN 授予 Get/Put/Delete/ListBucket 权限,而非授予更广泛的 S3 访问权限。

约束

必须做到
  • 从环境变量或绑定的 IAM 角色加载 AWS 凭证
  • 设置 default_acl=None,让存储桶策略(而非对象 ACL)控制访问权限
  • 为静态文件和媒体文件设置不同的 location 前缀,或使用不同的存储桶
  • 在 Django 4.2+ 中使用 STORAGES 字典(Django 5.2 LTS 和 6.0 的配置方式相同);DEFAULT_FILE_STORAGE/STATICFILES_STORAGE 已在 5.1 中移除,仅在低于 4.2 的版本中使用
  • 对任何会生成预签名 URL 的后端设置 custom_domain=None
  • 在测试中使用 Mock S3(InMemoryStorage 或 moto),而非访问真实存储桶
绝不能做
  • 不要在 settings.py 中硬编码 AWS_SECRET_ACCESS_KEY,也不要提交该密钥
  • 不要将 querystring_auth=True 与 custom_domain 混用(预签名会失效)
  • 不要在同一前缀下混放静态文件和媒体文件
  • 授予 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 — 核心 Django 模型、DRF 和 ORM 会生成此技能持久化到 S3 的文件
  • fullstack-guardian — 安全的端到端上传流程,以及对存储文件的访问控制
  • devops-engineer — 配置此技能所使用的 S3 存储桶、IAM 角色和 CloudFront 分发

文档

评论

支持 Markdown