Collectstatic error while deploying Django app to Heroku

81,668

Solution 1

I just updated to Django 1.10 today and had the exact same problem. Your static settings are identical to mine as well.

This worked for me, run the following commands:

  1. disable the collectstatic during a deploy

    heroku config:set DISABLE_COLLECTSTATIC=1

  2. deploy

    git push heroku master

  3. run migrations (django 1.10 added at least one)

    heroku run python manage.py migrate

  4. run collectstatic using bower

    heroku run 'bower install --config.interactive=false;grunt prep;python manage.py collectstatic --noinput'

  5. enable collecstatic for future deploys

    heroku config:unset DISABLE_COLLECTSTATIC

  6. try it on your own (optional)

    heroku run python manage.py collectstatic

future deploys should work as normal from now on

Solution 2

You have STATICFILES_DIRS configured to expect a static directory in the same directory as your settings.py file, so make sure it's there not somewhere else.

Also, do you have any files in that static directory? If you don't then git won't track it and so although it exists locally it won't exist in git. The usual solution to this is to create an empty file called .keep in the directory which will ensure that git tracks it. But once you have some static files in this directory then it won't be a problem anymore.

Solution 3

DO NOT disable collectstatic on heroku with heroku config:set DISABLE_COLLECTSTATIC=1. This will just hide the error and not make your app healthy.

Instead, it's better to understand why the collectstatic command fails because it means something is not right with your settings.

Step 1

Run locally both commands:

python manage.py collectstatic
python manage.py test

You should see one or more error messages. Most of the time, it's a missing variable (for ex: STATIC_ROOT) you must add to your project settings.py file.

It's necessary to add the test command because some collectstatic related issues will only surface with test, such as this one

Step 2

Once you've fixed all the error messages locally, push again to heroku.

Troubleshooting

Remember you can also run commands directly in your heroku VM. If you cannot reproduce locally, run the collecstatic command in heroku and check what's going on directly in your production environment:

python manage.py collectstatic --dry-run --noinput

Launch heroku VM

(Same goes for heroku console obviously)

Solution 4

Run python manage.py collectstatic locally and fix any errors. In my case there were reference errors that prevented that command from running successfully.

Solution 5

  • This error has occurred because you do not have staticfiles in your Project's Root Directory.

  • Don't worry. The solution is SIMPLE.

  • You only need TWO STEPS.

Step 1: Open your settings.py file and write

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

STATIC_ROOT = BASE_DIR / 'staticfiles'

Step 2: Run below given command in terminal in your Project's root directory. (If you are using any Virtual environment for Django Project then go inside your Virtual environment and then go into your Project's root directory and then run below given command.)

python manage.py collectstatic

Congrats : Your Problem is Solved.

Now, you can COMMIT and PUSH your "changes" so that it is reflected in your Repository and then you are good to go.

Share:
81,668
Stefano De Rosso
Author by

Stefano De Rosso

Updated on September 07, 2021

Comments

  • Stefano De Rosso
    Stefano De Rosso over 2 years

    I'm trying to deploy a Django app to Heroku, it starts to build, download and installs everything, but that's what I get when it comes to collecting static files

    $ python manage.py collectstatic --noinput
    remote:        Traceback (most recent call last):
    remote:          File "manage.py", line 10, in <module>
    remote:            execute_from_command_line(sys.argv)
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    remote:            utility.execute()
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 330, in execute
    remote:            self.fetch_command(subcommand).run_from_argv(self.argv)
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 390, in run_from_argv
    remote:            self.execute(*args, **cmd_options)
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 441, in execute
    remote:            output = self.handle(*args, **options)
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 168, in handle
    remote:            collected = self.collect()
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 98, in collect
    remote:            for path, storage in finder.list(self.ignore_patterns):
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/finders.py", line 112, in list
    remote:            for path in utils.get_files(storage, ignore_patterns):
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/utils.py", line 28, in get_files
    remote:            directories, files = storage.listdir(location)
    remote:          File "/app/.heroku/python/lib/python2.7/site-packages/django/core/files/storage.py", line 300, in listdir
    remote:            for entry in os.listdir(path):
    remote:        OSError: [Errno 2] No such file or directory: '/app/blogproject/static'
    remote: 
    remote:  !     Error while running '$ python manage.py collectstatic --noinput'.
    remote:        See traceback above for details.
    remote: 
    remote:        You may need to update application code to resolve this error.
    remote:        Or, you can disable collectstatic for this application:
    remote: 
    remote:           $ heroku config:set DISABLE_COLLECTSTATIC=1
    remote: 
    remote:        https://devcenter.heroku.com/articles/django-assets
    remote: 
    remote:  !     Push rejected, failed to compile Python app
    remote: 
    remote: Verifying deploy...
    remote: 
    remote: !   Push rejected to pin-a-voyage.
    

    This is the whole settings.py file

    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    import os
    import dj_database_url
    
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
    
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = '*********************'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    
    # Application definition
    
    INSTALLED_APPS = (
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'blog',
        'custom_user',
        'django_markdown',
        'parsley',
    )
    
    #### AUTH ###
    
    AUTH_USER_MODEL = 'custom_user.CustomUser'
    
    AUTHENTICATION_BACKENDS = (
        'custom_user.backends.CustomUserAuth',
        'django.contrib.auth.backends.ModelBackend',
        # 'django.contrib.auth.backends.RemoteUserBackend',
    )
    
    #############
    
    #### EMAIL ###
    
    EMAIL_USE_TLS = True
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_HOST_PASSWORD = '***' #my gmail password
    EMAIL_HOST_USER = '[email protected]' #my gmail username
    DEFAULT_FROM_EMAIL = '[email protected]'
    SERVER_EMAIL = '[email protected]'
    EMAIL_PORT = 587
    DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
    
    ##############
    
    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    )
    
    ROOT_URLCONF = 'blogproject.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'blogproject.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'blogproject',
            'USER': '***',
            'PASSWORD': '***',
            'HOST': 'localhost',
            'PORT': '',
        }
    }
    
    
    # Internationalization
    # https://docs.djangoproject.com/en/1.8/topics/i18n/
    
    LANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = True
    
    
    # Update database configuration with $DATABASE_URL.
    db_from_env = dj_database_url.config(conn_max_age=500)
    DATABASES['default'].update(db_from_env)
    
    # Honor the 'X-Forwarded-Proto' header for request.is_secure()
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    
    # Allow all host headers
    ALLOWED_HOSTS = ['*']
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.8/howto/static-files/
    
    STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
    STATIC_URL = '/static/'
    
    # Extra places for collectstatic to find static files.
    STATICFILES_DIRS = (
        os.path.join(PROJECT_ROOT, 'static'),
    )
    
    # Simplified static file serving.
    # https://warehouse.python.org/project/whitenoise/
    STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
    

    This is the structure of the project

    blog-project -- blog -- migrations
                         -- static
                         -- templates
                 -- blogproject
                 -- blogprojectenv
                 -- custom_user
                 -- media
                 -- .git
    

    Any thoughts?

  • Stefano De Rosso
    Stefano De Rosso about 8 years
    I have tried to do that, but it doesn't seem to work. I created one also in the root directory, just to try, but the result is the same.
  • AdjunctProfessorFalcon
    AdjunctProfessorFalcon almost 7 years
    This worked for me because I actually had an empty static directory in my project package in my Django app as all my static files were in the static directory inside the main app package.
  • Manas Chaturvedi
    Manas Chaturvedi over 6 years
    This worked like a charm! My static folder was empty and adding an empty .keep file did the trick for me.
  • citynorman
    citynorman over 6 years
    In my case I needed to fix some errors with python manage.py collectstatic so DISABLE_COLLECTSTATIC would have been a band aid...
  • Ben2pop
    Ben2pop over 6 years
    Hi Tom, in your step 4 I got the error :raise ImproperlyConfigured("You're using the staticfiles app " django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path. any idea ?
  • citynorman
    citynorman over 6 years
    As a side note, serving static files with whitenoise and debug=False on heroku ended up being a total clusterf*** and I couldn't get it to work after messing around for 2 days. I ended up setting up an aws s3+cloudfront with the staticfiles and setting STATIC_URL = 'https://xxxxxxxxxxxxxx.cloudfront.net' and it works beautifully.
  • TrialAndError
    TrialAndError almost 6 years
    I had /static completely ignored so it was not adding it at all. Thanks, it would've taken me forever to figure this out.
  • waqasgard
    waqasgard over 5 years
    Have no idea why this works but this solved my problem so +1.
  • Mark
    Mark over 5 years
    Thanks this helped me too. I created the static files directory in the app folder not the main project folder.
  • Kjell
    Kjell almost 5 years
    You have a typo there: I think it should be heroku config:set DISABLE_COLLECTSTATIC=1
  • Moaaz
    Moaaz over 3 years
    @Ben2pop, add STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') to your settings.py file, better under STATIC_URL
  • Ali Husham
    Ali Husham about 3 years
    when I ran heroku config:set DISABLE_COLLECTSTATIC=1 i got ` › Error: Missing required flag:` ` › -a, --app APP app to run command against` ` › See more help with --help`
  • NIKHIL CHANDRA ROY
    NIKHIL CHANDRA ROY about 3 years
    thanks, after put something in static folder then issue fixed
  • AfriPwincess
    AfriPwincess almost 3 years
    Thanks a lot. I created the static directory and adding a folder and an empty file to it and it works now.
  • blimpse
    blimpse almost 3 years
    What the heck does bower have to do with anything?
  • The Sammie
    The Sammie almost 3 years
    This is a helpful answer. Disabling COLLECTSTATIC is a workaround like someone mentioned in one of the answers below. I found out that for my case, I hadn't set the SECRET_KEY config var on Heroku and once I put it up, everything worked.
  • wjh18
    wjh18 over 2 years
    Wouldn't this enable DEBUG in production which is a big no-no? It should be set to false.
  • Alexander P
    Alexander P over 2 years
    Got error bash: bower: command not found
  • DevAdedoyin
    DevAdedoyin about 2 years
    This helped solve my problem. Thanks fam
  • The Ultraempoleon
    The Ultraempoleon almost 2 years
    How are the environmental variables defined?
  • Avishka Dambawinna
    Avishka Dambawinna almost 2 years
    Heroku app settings > Config Vars