DEV Community

Aaron Dave Siapuatco
Aaron Dave Siapuatco

Posted on

1 1 1

Setting Up AWS S3 with Django

Ever tried to build a CMS fearing scalability? Me neither, but when we code, we should always do best practices! So while Django thoughtfully provides a static folder for your assets, it will definitely not scale properly. So, this is where AWS S3 buckets come in! Offering a scalable solution for storing media files.

Despite Django's popularity and extensive documentation, setting up S3 integration can be challenging due to limited resources. After being stuck for a few days myself, I've created this tutorial to help others implement S3 buckets with Django quickly and efficiently.

🪣 AWS S3 Setup

First, let's create your shiny new S3 bucket:

  1. Log into AWS
  2. Navigate to the S3 service (hint: just search for "S3")
  3. Create a bucket with these super-important characteristics:
    • A globally unique name (get creative – my-awesome-project-media)
    • Public access settings tailored to your paranoia level
    • Create a folder called images/

🔐 IAM Permissions

Don't be that person using admin keys for everything. Create a dedicated IAM user:

  1. Head to IAM service
  2. Create a new policy with this magical JSON:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name/*",
                "arn:aws:s3:::your-bucket-name"
            ]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode
  1. Create a new IAM user, attach your shiny new policy
  2. Save those credentials like they're the secret recipe to your grandma's cookies

CORS Configuration

If your frontend will talk directly to S3:

  1. Find your bucket properties
  2. Scroll down to CORS configuration
  3. Add this policy (adjust to your needs):
[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET", "HEAD"],
        "AllowedOrigins": ["https://your-domain.com"], # Or just use * if not yet deployed
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]
Enter fullscreen mode Exit fullscreen mode

🐍 Django Configuration

Now let's connect our Django project and S3:

1. Install the necessary packages

pip install django-storages boto3 python-dotenv
Enter fullscreen mode Exit fullscreen mode

2. Create a .env file

AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_STORAGE_BUCKET_NAME=your-bucket-name
AWS_S3_REGION_NAME=your-region
Enter fullscreen mode Exit fullscreen mode

IMPORTANT: Add .env to your .gitignore file!

3. Update settings.py – The Control Center

import os
from dotenv import load_dotenv

# Load those secret environment variables
load_dotenv()

# Static files configuration (the classics)
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "<DJANGO_APP>/static"),  # Your app's static folder
]

# AWS S3 Configuration - The VIP section
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME')

# Advanced S3 settings for the power users
AWS_S3_FILE_OVERWRITE = False  # No file conflicts here!
AWS_DEFAULT_ACL = None  # Let the bucket decide
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'  # Fancy direct URLs

# Storage class optimization (your wallet will thank you)
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',  # Cache for a day
    'StorageClass': 'STANDARD'  # Pick your storage flavor
}

# Tell Django to use S3 for media storage
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# Media URL pointing to your S3 kingdom
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"
Enter fullscreen mode Exit fullscreen mode

4. Create a Model – The Simplest Part!

# models.py
from django.db import models

class Document(models.Model):
    def get_s3_path(instance, filename):
        return f"documents/{filename}"  # Your S3 bucket path

    title = models.CharField(max_length=100)
    file = models.FileField(upload_to=get_s3_path)  # This is where the magic happens!
    uploaded_at = models.DateTimeField(auto_now_add=True)
Enter fullscreen mode Exit fullscreen mode

That's it! Just use FileField or ImageField with upload_to and Django+S3 handles the rest. Magic! ✨

Testing Your Integration

Time to see if our hard work paid off:

  1. Create a document in your admin interface (the easy part)
  2. Upload a file (fingers crossed...)
  3. Check your S3 bucket (where did my file go?)
  4. Test the URL (the moment of truth!)

Pro Tips: Learn From My Mistakes

  1. Access Control:

    • Use AWS_DEFAULT_ACL = None unless you specifically need public files
  2. Credential Management:

    • Keep .env out of version control (your future employer will thank you)
    • Your IAM user should only have the permissions it needs (just S3)
    • For production, consider AWS IAM roles instead of access keys

fin.

Congrats! Your Django app is now ready to handle anything from a few profile pictures to millions of cat photos.

Happy coding!

Top comments (0)