20

I am trying to deploy my django app on heroku. All the static files are served by whitenoise and are migrated successfully. But how do I get my media files that are uploaded using ImageField to display during production.

my settings.py

STATIC_URL = '/static/'
STATIC_ROOT = 'C:/Users/Sak/mpro/feat/static/'
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

wsgi.py

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mpro.settings")

application = get_wsgi_application()

try:
  from django.core.wsgi import get_wsgi_application
  from whitenoise.django import DjangoWhiteNoise
  application = get_wsgi_application()
  application = DjangoWhiteNoise(application)   
  from dj_static import Cling
  application = Cling(get_wsgi_application())
except:
     pass

urls.py

urlpatterns = [
url(r'^', include('feat.urls', namespace="feat")),
url(r'^admin/', include(admin.site.urls)),
 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

All my media files are uploaded to base_dir/media/media and when whitenoise collects static files it only collects files at STATIC_ROOT, so how do I get my media files deployed. When I run heroku run ls I can see the folder media.

WutWut
  • 1,204
  • 2
  • 17
  • 31
  • 2
    Well, files in media is supposed to be runtime data, linked to the data in the database, so it is not copied, the same way it will not copy over data from the database. I suppose you could use fixtures if you need some initial data. Otherwise, you're pretty much on your own I believe. – spectras Jun 26 '15 at 12:49
  • I understand they are not copied the same way as staticfiles are but, there must be a way to add media images. May be even after production, if I want to add new images in my admin, there must be a way to store it somewhere such that they are copied too.May be in the static files folder where they are copied along with static files – WutWut Jun 26 '15 at 12:55
  • You can either upload them, which will cause Django to put them there, or you can copy over files manually, and assign `instance.image.path` to directly point at them in some script. Path should be relative to `MEDIA_ROOT`. – spectras Jun 26 '15 at 12:58
  • I tried uploading them in the admin panel of the site deployed by heroku but they weren't displayed. And I don't understand the second way that you have recommended. Can't I make some changes to the path of the media files such that when I upload them again, they are put there by django. – WutWut Jun 26 '15 at 13:07
  • Well, I don't know heroku, maybe they have something for this. I am pretty sure Django itself does not, and you'd have to make a short script/custom management comment to do that. – spectras Jun 26 '15 at 13:50
  • Any tips on how to do that? – WutWut Jun 26 '15 at 14:04
  • Well, sorry I don't have time enough to make a proper answer. Documentation about custom commands is here: https://docs.djangoproject.com/en/1.8/howto/custom-management-commands/ Page looks long, but you should only need the first section. – spectras Jun 26 '15 at 14:18
  • Try to not use `url(r'^', include('feat.urls', namespace="feat")),` instead use `url(r'^feat/', include('feat.urls', namespace="feat")),` i also experienced some problems with media and this solve for me. If this work you can redirect the base url `url(r'^$', RedirectView.as_view(url='/feat/')),` – Zartch Dec 27 '15 at 15:46

1 Answers1

10

So, first of all it's important to realise that if you have a bunch of files that are part of your project (including things like images and such) and are deployed along with it, they are more likely to be static files than media files in Django parlance.

Media files in Django are for runtime uploaded files. They will generally be stored with a corresponding db entry such as models.ImageField(upload_to='/photos') but that isn't necessarily so.

Your media setup is wrong for Heroku, as you shouldn't be writing to a directory on the server anyway (this is what you are telling Django to do with MEDIA_ROOT = os.path.join(BASE_DIR, "media").

Most commonly you would instead use an S3 bucket for media on Heroku. This is a fairly comprehensive explanation of that. You can probably skip the bit about CORS and go for open permissions on the bucket (depending on your use case). The important bits are:

# settings.py

# Tell django what URL to server your media from
MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN

# Tell Django to use the boto storage backend to save media files.
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

If you want to use S3 for static AND media storage, the link explains that too.

You might want to look at this repo for a pretty comprehensive run-down of the AWS settings and what they do, plus a nicely wrapped package to do some of it for you.

More generally I found Django Herokuify exceptionally useful for all the boilerplate on Heroku.

Tom Manterfield
  • 6,515
  • 6
  • 36
  • 52