django-storages-s3

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Django Storages S3

使用Django Storages对接AWS S3

Senior Django specialist for production-grade file storage on AWS S3 via
django-storages
and
boto3
— public and private media, static files, presigned URLs, and CloudFront.
资深Django专家出品,通过
django-storages
boto3
实现基于AWS S3的生产级文件存储方案——涵盖公共/私有媒体文件、静态文件、预签名URL及CloudFront配置。

When to Use This Skill

适用场景

  • Serving static and/or media files from AWS S3 instead of the local filesystem
  • Configuring the Django 4.2+
    STORAGES
    dict or legacy
    DEFAULT_FILE_STORAGE
  • Separating public (CDN-served) and private (presigned) file backends
  • Generating presigned download or direct browser-to-S3 upload URLs
  • Fronting S3 with CloudFront and writing a least-privilege IAM policy
  • Migrating local
    FileField
    /
    ImageField
    storage to S3 without code changes
  • Testing storage code without hitting S3
  • 从AWS S3而非本地文件系统提供静态文件和/或媒体文件服务
  • 配置Django 4.2+的
    STORAGES
    字典或旧版
    DEFAULT_FILE_STORAGE
  • 分离公共(CDN分发)和私有(预签名访问)文件后端
  • 生成预签名下载链接或浏览器直接上传至S3的URL
  • 为S3配置CloudFront前端并编写最小权限IAM策略
  • 将本地
    FileField
    /
    ImageField
    存储迁移至S3且无需修改代码
  • 在不访问真实S3的情况下测试存储相关代码

Core Workflow

核心流程

  1. Install & register
    pip install django-storages[s3] boto3
    ; add
    "storages"
    to
    INSTALLED_APPS
  2. Configure credentials — Load from env vars or rely on an attached IAM role; never hardcode
  3. Wire the
    STORAGES
    dict
    — Set
    default
    (media) and
    staticfiles
    backends with separate
    location
    prefixes
  4. Add named backends — Split public vs. private buckets/ACLs as additional
    STORAGES
    entries when needed
  5. Verify & test — Run
    collectstatic
    , confirm uploads land in S3, and mock S3 in tests with
    InMemoryStorage
    or
    moto
  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

Reference Guide

参考指南

Load detailed guidance based on context:
TopicReferenceLoad When
Settings & STORAGES
references/configuration.md
Core settings, 4.2+ vs legacy, CloudFront
Custom backends
references/custom-backends.md
Public vs. private buckets, per-field storage
Presigned URLs
references/presigned-urls.md
Download links, direct browser uploads
Testing & IAM
references/testing-storages.md
Mocking S3, IAM policy, common pitfalls
根据上下文加载详细指导:
主题参考文档适用场景
设置与STORAGES配置
references/configuration.md
核心设置、4.2+与旧版对比、CloudFront配置
自定义后端
references/custom-backends.md
公共/私有存储桶、按字段配置存储
预签名URL
references/presigned-urls.md
下载链接、浏览器直接上传
测试与IAM
references/testing-storages.md
S3模拟、IAM策略、常见陷阱

Minimal Working Example

最简可用示例

The snippet below demonstrates the core MUST DO constraints: env-loaded credentials,
STORAGES
dict, separate media/static locations, and
default_acl=None
on the media backend.
python
undefined
以下代码片段展示了必须遵守的核心约束:从环境加载凭证、使用
STORAGES
字典、分离媒体/静态文件路径、媒体后端设置
default_acl=None
python
undefined

settings.py

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"
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.

在EC2/ECS/Lambda上,完全省略密钥 — boto3会使用附加的IAM角色。

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/"

```python
STORAGES = { "default": { # 媒体文件上传 "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", "OPTIONS": { "bucket_name": AWS_STORAGE_BUCKET_NAME, "location": "media", "default_acl": None, # 依赖存储桶策略,而非单个对象的ACL "file_overwrite": False, "querystring_auth": False, # 公共对象 → 简洁URL }, }, "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/"

```python

models.py — uploads go straight to S3 on save()

models.py — 保存时直接上传至S3

from django.db import models
class Document(models.Model): file = models.FileField(upload_to="docs/") # uses STORAGES["default"]
undefined
from django.db import models
class Document(models.Model): file = models.FileField(upload_to="docs/") # 使用STORAGES["default"]
undefined

Auditing an Existing Configuration

现有配置审计

When reviewing a project that already uses S3 (not greenfield), walk this checklist — each item is a constraint below rephrased as "find X, confirm Y":
  1. Credentials
    grep -rn "AWS_SECRET_ACCESS_KEY\|aws_secret" settings/
    → confirm values come from
    os.environ
    /
    django-environ
    or an IAM role, never literals committed to the repo.
  2. ACLs
    grep -rn "default_acl\|AWS_DEFAULT_ACL" .
    → on buckets created after April 2023, every value must be
    None
    . Any
    "public-read"
    /
    "private"
    will raise
    AccessControlListNotSupported
    ; public access belongs in a bucket policy.
  3. Storage backend — confirm Django 4.2+ uses the
    STORAGES
    dict, not
    DEFAULT_FILE_STORAGE
    /
    STATICFILES_STORAGE
    (removed in Django 5.1, so silently ignored on 5.1/5.2/6.0); confirm the static class is
    S3StaticStorage
    , not a fabricated name.
  4. Locations — confirm
    default
    (media) and
    staticfiles
    have distinct
    location
    prefixes or buckets so
    collectstatic
    never collides with uploads.
  5. Region — confirm
    region_name
    (or the global
    AWS_S3_REGION_NAME
    ) matches the bucket's real region and that
    AWS_S3_CUSTOM_DOMAIN
    includes the region segment for non-
    us-east-1
    buckets.
  6. Presigning — for private backends, confirm
    querystring_auth=True
    and
    custom_domain=None
    ; confirm presigned
    .url()
    results aren't cached past
    AWS_QUERYSTRING_EXPIRE
    .
  7. Overwrite cleanup — where
    file_overwrite=False
    , confirm replaced files are explicitly deleted (otherwise superseded objects leak).
  8. IAM — confirm the policy grants only
    Get/Put/Delete/ListBucket
    on the bucket ARN, not broader S3 access.
当审查已使用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访问权限。

Constraints

约束规范

MUST DO

必须遵守

  • Load AWS credentials from environment variables or an attached IAM role
  • Set
    default_acl=None
    so bucket policies (not object ACLs) control access
  • Give static and media files separate
    location
    prefixes or separate buckets
  • Use the
    STORAGES
    dict on Django 4.2+ (same config through 5.2 LTS and 6.0);
    DEFAULT_FILE_STORAGE
    /
    STATICFILES_STORAGE
    were removed in 5.1, so reserve them for < 4.2 only
  • Set
    custom_domain=None
    on any backend that issues presigned URLs
  • Mock S3 (
    InMemoryStorage
    or
    moto
    ) in tests instead of hitting real buckets
  • 从环境变量或附加的IAM角色加载AWS凭证
  • 设置
    default_acl=None
    ,通过存储桶策略(而非对象ACL)控制访问
  • 为静态文件和媒体文件设置不同的
    location
    前缀或使用不同的存储桶
  • 在Django 4.2+上使用
    STORAGES
    字典(该配置兼容5.2 LTS和6.0版本);
    DEFAULT_FILE_STORAGE
    /
    STATICFILES_STORAGE
    已在5.1中移除,仅在Django <4.2版本中使用
  • 对任何生成预签名URL的后端设置
    custom_domain=None
  • 在测试中模拟S3(使用
    InMemoryStorage
    moto
    ),而非访问真实存储桶

MUST NOT DO

禁止操作

  • Hardcode
    AWS_SECRET_ACCESS_KEY
    in
    settings.py
    or commit it
  • Mix
    querystring_auth=True
    with a
    custom_domain
    (presigning breaks)
  • Mix static and media files under the same prefix
  • Grant the IAM user broader than
    Get/Put/Delete/ListBucket
    on the bucket ARN
  • Rely on per-object ACLs on buckets created after April 2023 (ACLs disabled by default)
  • settings.py
    中硬编码
    AWS_SECRET_ACCESS_KEY
    或提交到仓库
  • 同时设置
    querystring_auth=True
    custom_domain
    (预签名功能会失效)
  • 将静态文件和媒体文件放在同一前缀下
  • 为IAM用户授予存储桶ARN以外的更宽泛S3访问权限
  • 在2023年4月之后创建的存储桶上依赖单个对象的ACL(默认禁用ACL)

Knowledge Reference

知识参考

django-storages, S3Boto3Storage, S3StaticStorage, boto3, STORAGES dict, presigned URLs, generate_presigned_post, CloudFront, IAM policy, InMemoryStorage, moto
django-storages, S3Boto3Storage, S3StaticStorage, boto3, STORAGES dict, presigned URLs, generate_presigned_post, CloudFront, IAM policy, InMemoryStorage, moto

Related Skills

相关技能

  • django-expert
    — core Django models, DRF, and ORM that produce the files this skill persists to S3
  • fullstack-guardian
    — secure end-to-end upload flows and access control around stored files
  • devops-engineer
    — provisioning the S3 buckets, IAM roles, and CloudFront distributions this skill targets
  • django-expert
    — 核心Django模型、DRF和ORM,负责生成本技能需存储到S3的文件
  • fullstack-guardian
    — 安全的端到端上传流程及存储文件的访问控制
  • devops-engineer
    — 配置本技能所需的S3存储桶、IAM角色和CloudFront分发