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)