Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django serves static files with runserver but not with foreman

I have the opposite problem to the one described in this question.

My Django site works correctly when the server is started using manage.py runserver but static files are not served when the server is started with foreman start.

My directory structure:

project_name/
  project/
    settings.py
    ...
  app/
    ...
  venv/
    ...
  public/
    static/
      # static files go here #
    media/
      ...
  Procfile
  requirements.txt
  manage.py

Procfile (as described in the Getting Started with Django on Heroku tutorial):

web: gunicorn project.wsgi

settings.py:

import os
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
UP_ROOT = os.path.abspath(os.path.join(SITE_ROOT, '..'))
...
MEDIA_ROOT = UP_ROOT + '/public/media/'
...
STATIC_ROOT = UP_ROOT + '/public/static'
...
STATIC_URL = '/static/'
...
STATICFILES_DIRS = (
UP_ROOT + '/public',
UP_ROOT + '/public/static',
)

Like I said, all of this works correctly with runserveron my local machine, but not with foreman start.

Will post more info if requested.

like image 582
mbaytas Avatar asked Apr 23 '13 13:04

mbaytas


1 Answers

The difference between runserver and foreman:

Django's runserver command serves static files because django.contrib.staticfiles automatically searches through your project's static folders for you (provided a few prerequisites are in place here) and returns them on static requests.

Foreman, however, is a separate utility from Django and knows nothing about Django's internals. So, you need some added help. Two good options are dj-static or whitenoise. Either can be installed using pip. You will need to make a small modification to your wsgi.py file, as described in the setup instructions for whichever you choose (see links).

Both dj-static and whitenoise look in STATIC_ROOT in your settings.py file for static files. This is different than Django's runserver, which automatically traverses the various static folders in your project. This means you need to run manage.py collectstatic (which gathers your static files into STATIC_ROOT) before dj-static or whitenoise will find them.

Here is a set of example steps (for whitenoise):

Run:

pip install whitenoise

Modify wsgi.py to look like this:

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = DjangoWhiteNoise(get_wsgi_application())

Then static files will work:

# Run collectstatic before foreman whenever you've changed static files
python manage.py collectstatic
foreman start

Foreman requires a little more effort than runserver. However, foreman can closely mimic a production environment, whereas runserver will not (hopefully, it will not). Using dj-static or whitenoise in production is an okay choice in many situations. So, developing using foreman with dj-static or whitenoise will give you reassurance that major problems won't surprise you when your site moves to production. You don't get that reassurance from some other options (e.g. adding 'django.views.static.serve' to urls.py).

like image 90
Christian Abbott Avatar answered Sep 23 '22 02:09

Christian Abbott