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 runserver
on my local machine, but not with foreman start
.
Will post more info if requested.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With