Skip to content

Django File Upload S3 Fix

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Django File Upload S3 Fix. We cover key concepts, practical examples, and best practices.

The Problem

Storing user-uploaded files on the local filesystem doesn't scale. In production with multiple web servers, a file uploaded to server A isn't available on server B. S3 provides centralized storage.

Quick Fix

Wrong — local filesystem storage

# settings.py
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'

Output: Files stored on local disk. In multi-server deployments, files are not shared. Backups must include uploaded files.

Correct — django-storages with S3

# settings.py
INSTALLED_APPS = [
    'storages',
    ...
]

AWS_ACCESS_KEY_ID = 'your-access-key'
AWS_SECRET_ACCESS_KEY = 'your-secret-key'
AWS_STORAGE_BUCKET_NAME = 'myapp-media'
AWS_S3_REGION_NAME = 'us-east-1'
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = 'private'
AWS_S3_VERIFY = True
AWS_S3_CUSTOM_DOMAIN = 'media.myapp.com'  # Optional: CDN

STORAGES = {
    'default': {
        'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage',
    },
    'staticfiles': {
        'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage',
    },
}

Output: Files uploaded via FileField are stored in S3. Available from any server.

Model with file upload

from django.db import models

class Document(models.Model):
    title = models.CharField(max_length=100)
    file = models.FileField(upload_to='documents/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

Output: File stored at s3://myapp-media/documents/filename.pdf.

Direct S3 upload (frontend → S3, skipping server)

# Generate presigned URL
import boto3

def get_upload_url(request):
    s3 = boto3.client('s3')
    url = s3.generate_presigned_url(
        'put_object',
        Params={
            'Bucket': 'myapp-media',
            'Key': f'uploads/{request.user.id}/{uuid.uuid4()}',
        },
        ExpiresIn=3600,
    )
    return Response({'upload_url': url})

Output: Client uploads directly to S3. Server doesn't handle the file bytes.

Serving private files via S3

AWS_QUERYSTRING_AUTH = True
AWS_QUERYSTRING_EXPIRE = 3600

Output: File URLs include signed parameters that expire after 1 hour.

Prevention

  • Use django-storages with S3Boto3Storage for production file storage.
  • Set AWS_DEFAULT_ACL = 'private' for user files.
  • Use CloudFront or CDN for public media delivery.

Common Mistakes with file upload s3

  1. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  2. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
  3. Using return to exit a function early instead of wrapping a pure value in the monad

These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What permissions does the S3 bucket need?

The IAM user needs s3:PutObject, s3:GetObject, s3:DeleteObject, and s3:ListBucket on the bucket.

How do I migrate existing files to S3?

Use Django's Storage API or a management command: copy from filesystem to S3, then update MEDIA_ROOT settings.

Can I use S3 with django-debug-toolbar?

Yes. The toolbar works normally. File URLs will point to S3 instead of local paths.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro