title: Using Amazon S3 with Heroku Django to store image uploads
body: <p>I have a Django project deployed to Heroku. Locally, it works fine. However, there is a problem in production: the image files uploaded by the admin cannot be found and displayed.</p>
  
  <p>The error message is:</p>
  
  <pre><code>Failed to load resource: the server responded with a status of 404 (Not Found)
  </code></pre>
  
  <p>and the URL that the server tried is something like this:</p>
  
  <pre><code>https://thawing-escarpment-####.herokuapp.com/image.png
  </code></pre>
  
  <p>To fix this, I attempted to use Amazon S3 as storage for the media files. I'm completely new at this, so I tried several tutorials and nothing worked.</p>
  
  <p>Using <a href="https://devcenter.heroku.com/articles/s3-upload-python" rel="nofollow">this Heroku tutorial</a> for reference, I created a bucket called <code>my-website-assets</code></p>
  
  <p>and then set up the configurations for Heroku:</p>
  
  <pre><code>heroku config:set AWS_ACCESS_KEY=xxx AWS_SECRET_KEY=yyy
  heroku config:set S3_BUCKET = my-website-assets
  </code></pre>
  
  <p>and then modified the bucket CORS configuration:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"&gt;
      &lt;CORSRule&gt;
          &lt;AllowedOrigin&gt;thawing-escarpment-####.herokuapp.com&lt;/AllowedOrigin&gt;
          &lt;AllowedMethod&gt;GET&lt;/AllowedMethod&gt;
          &lt;AllowedMethod&gt;POST&lt;/AllowedMethod&gt;
          &lt;AllowedMethod&gt;PUT&lt;/AllowedMethod&gt;
          &lt;AllowedHeader&gt;*&lt;/AllowedHeader&gt;
      &lt;/CORSRule&gt;
  &lt;/CORSConfiguration&gt;
  </code></pre>
  
  <p>In <code>app/models.py</code> I have:</p>
  
  <pre><code>class SpotlightContent(models.Model):
      title = models.CharField(max_length=300)
      image = models.ImageField(upload_to="")
      description = models.TextField()
  </code></pre>
  
  <p>In <code>templates/home.html</code>:</p>
  
  <pre><code>{% for content in spotlight_contents %}
      &lt;img src="{{ content.image.url }}" alt="{{ content.title }}" width="140" height="140"&gt;
      &lt;p&gt;{{ content.description }}&lt;/p&gt;
  {% endfor %}
  </code></pre>
  
  <p>In my <code>settings.py</code> file I made changes to the <code>MEDIA_URL</code> and <code>MEDIA_ROOT</code>:</p>
  
  <pre><code>STATIC_URL = '/static/'
  
  STATIC_ROOT = os.path.join(BASE_DIR, 'static', 'static_root')
  
  STATICFILES_DIRS = (
      os.path.join(BASE_DIR, 'static', 'static_dirs'),
  )
  
  ADMIN_MEDIA_PREFIX = 'https://s3.amazonaws.com/my-website-assets/'
  MEDIA_URL = 'https://s3.amazonaws.com/my-website-assets/'
  MEDIA_ROOT = ''
  </code></pre>
  
  <p>After these changes, I logged back into the Django, added a new Spotlight object, and refreshed the web page. The image still could not be loaded, so I checked the source code:</p>
  
  <pre><code>&lt;img src="https://s3.amazonaws.com/my-website-assets/test_icon.png" alt="Test" width="140" height="140"&gt;
  &lt;p&gt;This is a test. Please work!&lt;/p&gt;
  </code></pre>
  
  <p>Although the URL is an Amazon AWS one, the image resource could not be found, which leads me to believe that it was not added properly. Does anyone know how to get this to work? Thanks in advance.</p>