I've followed the official Heroku docs on Django and Static Assets; I've installed dj-static
and added it to my requirements.txt
file, properly configured all the variables in my settings.py
file:
STATIC_ROOT = os.path.join(CONFIG_ROOT, 'served/static/')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(CONFIG_ROOT, 'static'),
)
And this is what my wsgi.py
looks like:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_project.settings")
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
The contents of Procfile
:
web: gunicorn --bind 0.0.0.0:$PORT my_django_project.wsgi:application
In the docs, it says that "collectstatic is run automatically when it is configured properly." But when I navigate to my site there's clearly no css.
I've tried debugging using heroku run
, but that just copies the static files as expected.
I've noticed that when I include the collectstatic
command in my Procfile
, i.e.
web: python my_django_project/manage.py collectstatic --noinput ; gunicorn -b 0.0.0.0:$PORT my_django_project.wsgi:application
...that works as expected, and the static files are served.
However what's strange about that is when I run heroku run bash
and look inside the directory that STATIC_ROOT
is pointing to, there's nothing there! In fact, the entire served/
directory is missing, and yet, the static files are still being served!
I'd still like to know why isn't collectstatic
being run automatically though -- like mentioned in the docs -- when I deploy my Django app to Heroku.
It looks like you might be using a specific settings module for Heroku/production. Further, you've set the environment variable DJANGO_SETTINGS_MODULE
to point to this settings module (and that way, when the app runs, Django knows to use that one and not, say, your default/development one). Finally, you've probably configured static asset settings in Heroku/production settings module (perhaps, STATIC_ROOT
).
Okay, so if this is all correct, then here is the issue: heroku environment variables are only set at serve-time, not at compile-time. This is important because collectstatic
is a compile-time operation for Heroku. (Heroku goes through 2 stages when you push: 1) compiling, which involves setting the application up (collectstatic
, syncdb
, etc) 2) serving, the normal operation of your application).
So, essentially, you've done everything correctly, but Heroku hasn't exposed your environment variables, including your specification of a different settings module, to collectstatic
.
To have your environment variables set to compile-time, enable Heroku's user-env-compile
lab feature like this:
heroku labs:enable user-env-compile
I think this is a silly thing to do by default, and would be interested in hearing why Heroku thought it was a good idea.
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