Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't collectstatic being run automatically when I deploy my Django app to Heroku?

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.

like image 949
3cheesewheel Avatar asked Oct 16 '13 20:10

3cheesewheel


1 Answers

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.

like image 73
t-mart Avatar answered Sep 30 '22 14:09

t-mart