When I attended the London Django Meetup in May one of my fellow attendees asked how best to test files uploaded to Amazon S3 via a form. I used the question as the basis of a talk I gave at a later meet up in July. This post is the written form of that talk I gave.

When I write tests I try and patch all external network requests in order to:

Get the boilerplate code out of the way

The full source code for this tutorial can be found on GitHub.

To start, I installed various requirements I'll need both to run and to test this project:

$ cat requirements.txt Django == 1 .6.5 argparse == 1 .2.1 boto == 2 .30.0 django-boto == 0 .3.1 django-storages == 1 .1.8 mock == 1 .0.1 wsgiref == 0 .1.2 $ pip install -r requirements.txt

I then created a Dajngo project called meetup-testing and created a candidate application within it. Here is the layout of the files and folders:

$ tree . ├── base │ ├── __init__.py │ ├── local_settings.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── candidate │ ├── admin.py │ ├── fixtures │ │ └── gradient.jpg │ ├── forms.py │ ├── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py ├── README.md ├── requirements.txt └── templates ├── candidate.html └── thanks.html

I use boto to perform the I/O between my server and Amazon S3. It requires an access key id, secret access key and bucket name. I've kept these out of settings.py and instead placed them in local_settings.py which is excluded from the git repo. I also took SECRET_KEY out of the boilerplate settings.py Django generates and placed it in local_settings.py as well.

$ cat base/local_settings.py AWS_S3_ACCESS_KEY_ID = 'Get this from Amazon' AWS_S3_SECRET_ACCESS_KEY = 'This as well' AWS_STORAGE_BUCKET_NAME = 'your-s3-bucket-name' SECRET_KEY = 'A long string with many different types of characters'

In settings.py I made the following additions to the boilerplate file:

import os BASE_DIR = os . path . dirname ( os . path . dirname ( __file__ )) TEMPLATE_DIRS = os . path . join ( BASE_DIR , 'templates' ) INSTALLED_APPS = ( 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'storages' , 'candidate' , ) DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

And, at the very bottom of settings.py I added the following in: