4

I have my website finally working properly, but media files aren't served when debug = False what should I do? I've went through hell trying to make it work with nginx following this tutorial but it kept breaking and not serving static among other things, so I went with pure gunicorn and whitenoise. I really am not an expert at deploying, only development. Please help. Security isn't a problem with media files because only the admin can upload them, not end-users. Specifically I need to know if it's the end of the world leaving debug = True just for media files. Or if there's an easy way to serve them with debug = False.

  • When you say media files aren't served, does that mean a 404 is returned? What if you try a URL like /static//? – Dashdrum Oct 30 '19 at 16:51

3 Answers3

1

You shouldn’t use DEBUG=True in production, but if you are trying to test Whitenoise in development and get your medias served as well, this is the solution I came up with:

Replace in urls.py, this bit:

if settings.DEBUG:
    urlpatterns = [
        # ... the rest of your URLconf goes here ...
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

with:

if settings.DEBUG or settings.STAGE == 'local':
    urlpatterns.extend(
        [re_path(r'^%s(?P<path>.*)$' % re.escape(settings.MEDIA_URL.lstrip('/')), serve, kwargs={'document_root': settings.MEDIA_ROOT})]
    )

the critical part is to have a STAGE variable to indicate in which environment are you running the site.

Vlax
  • 1,447
  • 1
  • 18
  • 24
0

It is possible to serve both static and media files with just vanilla django in production but they clearly would prefer that you do not.

For static files you can either take the Whitenoise route or in wsgi.py:

  import os

from django.core.wsgi import get_wsgi_application
from django.conf import settings
from django.contrib.staticfiles.handlers import StaticFilesHandler


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_project.settings')


application = StaticFilesHandler(get_wsgi_application())

The StaticFilesHandler is WSGI middleware that intercepts calls to the static files directory, as defined by the STATIC_URL setting, and serves those files.I use this with a default Gunicorn server and it works fine. Not as efficient as using whitenoise but for small projects this will do fine.

For serving media files locally you need to add this to your main project urls.py:

from django.urls import re_path
from django.conf import settings
from django.views.static import serve

urlpatterns = [ re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT})]

For settings.py:

STATIC_URL = "static/"
MEDIA_URL = "media/"
STATICFILES_DIRS = [BASE_DIR / "static" ]  
STATIC_ROOT = BASE_DIR / "staticfiles"  
MEDIA_ROOT = BASE_DIR / "media"
STATICFILES_STORAGE = "django.contrib.staticfiles.storage.StaticFilesStorage"

Provided you put your media in a basedirectory media folder and static in the static folder. Again not as fast or safe as a dedicated media bucket but honestly fine for small projects.

Mike B
  • 11
  • 3
-1

Here's how I've setup Whitenoise to serve static files for my application. I am using RedHat 7, but things should be similar in Ubuntu. My Django version is 1.11.

Note that it is NOT safe to run with DEBUG=True outside of your development environment.

First, I setup an environment variable pointing to the location of the static files:

export DJANGO_STATIC_ROOT=/home/<user>/<project>/staticfiles

In settings.py:

## Static files

STATIC_URL = '/static/'

if DEBUG:
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
else:
    STATIC_ROOT = environ['DJANGO_STATIC_ROOT']

## Whitenoise - Insert in 2nd place after SecurityMiddleware

MIDDLEWARE_CLASSES.insert(1,'whitenoise.middleware.WhiteNoiseMiddleware')

# Add app before django.contrib.staticfiles to enable Whitenoise in development

for i, app in enumerate(INSTALLED_APPS):
    if app == 'django.contrib.staticfiles':
        insert_point = i
INSTALLED_APPS.insert(insert_point,'whitenoise.runserver_nostatic')

Each time you deploy the app, be sure to run the collectstatic command to update the files in your DJANGO_STATIC_ROOT location:

./manage.py collectstatic

Best of luck!

Dashdrum
  • 657
  • 1
  • 4
  • 9
  • I have static working fine with gunicorn and whitenoise, what is not being served are my media files. –  Oct 30 '19 at 19:33