Skip to main content

Add direct uploads to S3 functionality with a progress bar to file input fields.

Project description


Directly upload files to S3 compatible services with Django.


Install with Pip:
pip install django-s3direct

Access setup

When setting up access credentials you have two options:

Option 1:

Generate access credentials and add them directly to your Django settings. If using Amazon S3 you'll also need to create an IAM policy which grants permission to upload to your bucket for your newly created credentials.

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Action": [
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"

Option 2:

Use the EC2 instance profile and its attached IAM role (AWS only)
Ensure the following trust policy is in place in addition to the policy above. You'll also need the boto3 package installed.

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Principal": {
        "Service": ""
      "Action": "sts:AssumeRole"

CORS setup

Add a CORS policy to your bucket. Note the ETag header is important as it is used for multipart uploads. For more information see here.

If using Digital Ocean Spaces you must upload the CORS config via the API/s3cmd CLI (as you can't add the ExposeHeader rule). See here for more details.


Django Setup


    'APP_DIRS': True,


# If these are set to None, the EC2 instance profile and IAM role are used.
AWS_ACCESS_KEY_ID = 'your-aws-access-key-id'
AWS_SECRET_ACCESS_KEY = 'your-aws-secret-access-key'

# Bucket name
AWS_STORAGE_BUCKET_NAME = 'your-aws-s3-bucket-name'

# The region of your bucket, more info:
AWS_S3_REGION_NAME = 'eu-west-1'

# The endpoint of your bucket, more info:

    'example_destination': {
        # "key" [required] The location to upload file
        #       1. String: folder path to upload to
        #       2. Function: generate folder path + filename using a function  
        'key': 'uploads/images',

        # "auth" [optional] Limit to specfic Django users
        #        Function: ACL function
        'auth': lambda u: u.is_staff,

        # "allowed" [optional] Limit to specific mime types
        #           List: list of mime types
        'allowed': ['image/jpeg', 'image/png', 'video/mp4'],

        # "bucket" [optional] Bucket if different from AWS_STORAGE_BUCKET_NAME
        #          String: bucket name
        'bucket': 'custom-bucket',

        # "endpoint" [optional] Endpoint if different from AWS_S3_ENDPOINT_URL
        #            String: endpoint URL
        'endpoint': 'custom-endpoint',

        # "region" [optional] Region if different from AWS_S3_REGION_NAME
        #          String: region name
        'region': 'custom-region', # Default is 'AWS_S3_REGION_NAME'

        # "acl" [optional] Custom ACL for object, default is 'public-read'
        #       String: ACL
        'acl': 'private',

        # "cache_control" [optional] Custom cache control header
        #                 String: header
        'cache_control': 'max-age=2592000',

        # "content_disposition" [optional] Custom content disposition header
        #                       String: header
        'content_disposition': lambda x: 'attachment; filename="{}"'.format(x),

        # "content_length_range" [optional] Limit file size
        #                        Tuple: (from, to) in bytes
        'content_length_range': (5000, 20000000),

        # "server_side_encryption" [optional] Use serverside encryption
        #                          String: encrytion standard
        'server_side_encryption': 'AES256',

        # "allow_existence_optimization" [optional] Checks to see if file already exists,
        #                                returns the URL to the object if so (no upload)
        #                                Boolean: True, False
        'allow_existence_optimization': False,
    'example_destination_two': {
        'key': lambda filename, args: args + '/' + filename,
    	'key_args': 'uploads/images',

urlpatterns = [
    url(r'^s3direct/', include('s3direct.urls')),

Run python collectstatic if required.

Use in Django admin

from django.db import models
from s3direct.fields import S3DirectField

class Example(models.Model):
    video = S3DirectField(dest='example_destination')

Use the widget in a custom form

from django import forms
from s3direct.widgets import S3DirectWidget

class S3DirectUploadForm(forms.Form):
    images = forms.URLField(widget=S3DirectWidget(dest='example_destination'))

*Optional. You can modify the HTML of the widget by overiding template s3direct/templates/s3direct-widget.tpl

from django.views.generic import FormView
from .forms import S3DirectUploadForm

class MyView(FormView):
    template_name = 'form.html'
    form_class = S3DirectUploadForm


    <meta charset="utf-8">
    {{ }}
    <form action="" method="post">{% csrf_token %}
        {{ form.as_p }}


Examples of both approaches can be found in the examples folder. To run them:

$ git clone
$ cd django-s3direct
$ python install
$ cd example

# Add config to your environment
export AWS_ACCESS_KEY_ID='…'
export AWS_S3_REGION_NAME='…'
export AWS_S3_ENDPOINT_URL='…'

$ python migrate
$ python createsuperuser
$ python runserver

Visit http://localhost:8000/admin to view the admin widget and http://localhost:8000/form to view the custom form widget.


$ git clone
$ cd django-s3direct

# Add your AWS keys/details to .env file and export
$ cp .env-dist .env

# Build docker image
$ docker build . --build-arg SKIP_TOX=true -t s3direct
$ docker run -itv $(pwd):/code -p 8000-8001:8000-8001 --env-file .env s3direct bash
$ npm i

# Install locally
$ python develop

# Run examples
$ python example/ migrate
$ python example/ createsuperuser
$ python example/ runserver

# Run tox tests
$ tox

# Run tests
$ npm run test

# Run frontend bundler and Django server
$ npm run dev

# Watch and build frontend (dev)
$ npm run watch

# Build frontend (prod)
$ npm run build

# Format python // PEP8
$ npm run yapf

# Upload to PYPI
$ npm run pypi

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for django-s3direct, version 1.1.8
Filename, size File type Python version Upload date Hashes
Filename, size django_s3direct-1.1.8-py2.7.egg (175.2 kB) File type Egg Python version 2.7 Upload date Hashes View
Filename, size django_s3direct-1.1.8-py3.7.egg (175.3 kB) File type Egg Python version 3.7 Upload date Hashes View
Filename, size django-s3direct-1.1.8.tar.gz (138.2 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring DigiCert DigiCert EV certificate Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page