Package: django-s3direct
django-s3directDirectly upload files to S3 compatible services with Django.InstallationInstall with Pip:pip install django-s3directAccess setupWhen 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":[{"Action":["s3:AbortMultipartUpload","s3:GetObject","s3:ListMultipartUploadParts","s3:PutObject","s3:PutObjectAcl"],"Effect":"Allow","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 theboto3package installed.{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}CORS setupAdd a CORS policy to your bucket. Note the ETag header is
important as it is used for multipart uploads. For more information seehere.[{"AllowedHeaders":["*"],"AllowedMethods":["GET","HEAD","PUT","POST","DELETE"],"AllowedOrigins":["http://localhost:8080"],"ExposeHeaders":["ETag"],"MaxAgeSeconds":3000}]Django Setupsettings.pyINSTALLED_APPS=[...'s3direct',...]TEMPLATES=[{...'APP_DIRS':True,...}]# AWS# 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 nameAWS_STORAGE_BUCKET_NAME='your-aws-s3-bucket-name'# The region of your bucket, more info:# http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_regionAWS_S3_REGION_NAME='eu-west-1'# The endpoint of your bucket, more info:# http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_regionAWS_S3_ENDPOINT_URL='https://s3.eu-west-1.amazonaws.com'S3DIRECT_DESTINATIONS={'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':lambdau: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':lambdax:'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':lambdafilename,args:args+'/'+filename,'key_args':'uploads/images',}}urls.pyurlpatterns=[...url(r'^s3direct/',include('s3direct.urls')),...]Runpython manage.py collectstaticif required.Use in Django adminmodels.pyfromdjango.dbimportmodelsfroms3direct.fieldsimportS3DirectFieldclassExample(models.Model):video=S3DirectField(dest='example_destination')Use the widget in a custom formforms.pyfromdjangoimportformsfroms3direct.widgetsimportS3DirectWidgetclassS3DirectUploadForm(forms.Form):images=forms.URLField(widget=S3DirectWidget(dest='example_destination'))*Optional.You can modify the HTML of the widget by overiding templates3direct/templates/s3direct-widget.tplviews.pyfromdjango.views.genericimportFormViewfrom.formsimportS3DirectUploadFormclassMyView(FormView):template_name='form.html'form_class=S3DirectUploadFormtemplates/form.html<html><head><metacharset="utf-8"/><title>s3direct</title>{{ form.media }}</head><body><formaction=""method="post">{% csrf_token %} {{ form.as_p }}</form></body></html>ExamplesExamples of both approaches can be found in the examples folder. To run them:$gitclonegit@github.com:bradleyg/django-s3direct.git
$cddjango-s3direct
$pythonsetup.pyinstall
$cdexample# Add config to your environmentexportAWS_ACCESS_KEY_ID='…'exportAWS_SECRET_ACCESS_KEY='…'exportAWS_STORAGE_BUCKET_NAME='…'exportAWS_S3_REGION_NAME='…'exportAWS_S3_ENDPOINT_URL='…'$pythonmanage.pymigrate
$pythonmanage.pycreatesuperuser
$pythonmanage.pyrunserverVisithttp://localhost:8080/adminto view the admin widget andhttp://localhost:8080/formto view the custom form widget.Development$gitclonegit@github.com:bradleyg/django-s3direct.git
$cddjango-s3direct# Add your AWS keys/details to .env file and export$cp.env-dist.env# Frontend deps$npmi# Install locally$pythonsetup.pydevelop# Run examples$pythonexample/manage.pymigrate
$pythonexample/manage.pycreatesuperuser
$pythonexample/manage.pyrunserver0.0.0.0:8080# Run tests$npmruntest# Run frontend bundler and Django server$npmrundev# Watch and build frontend (dev)$npmrunwatch# Build frontend (prod)$npmrunbuild# Format python // PEP8$npmrunyapf# Upload to PYPI$npmrunpypi