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:
- Log into AWS
- Navigate to the S3 service (hint: just search for "S3")
- 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/
- A globally unique name (get creative –
🔐 IAM Permissions
Don't be that person using admin keys for everything. Create a dedicated IAM user:
- Head to IAM service
- 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"
]
}
]
}
- Create a new IAM user, attach your shiny new policy
- Save those credentials like they're the secret recipe to your grandma's cookies
CORS Configuration
If your frontend will talk directly to S3:
- Find your bucket properties
- Scroll down to CORS configuration
- 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
}
]
🐍 Django Configuration
Now let's connect our Django project and S3:
1. Install the necessary packages
pip install django-storages boto3 python-dotenv
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
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/"
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)
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:
- Create a document in your admin interface (the easy part)
- Upload a file (fingers crossed...)
- Check your S3 bucket (where did my file go?)
- Test the URL (the moment of truth!)
Pro Tips: Learn From My Mistakes
-
Access Control:
- Use
AWS_DEFAULT_ACL = None
unless you specifically need public files
- Use
-
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
- Keep
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)