85

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 = 'voyage.pin@gmail.com' #my gmail username
DEFAULT_FROM_EMAIL = 'voyage.pin@gmail.com'
SERVER_EMAIL = 'voyage.pin@gmail.com'
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?

Moe Far
  • 2,742
  • 2
  • 23
  • 41
Stefano De Rosso
  • 1,309
  • 1
  • 14
  • 27

21 Answers21

100

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

Community
  • 1
  • 1
tomcounsell
  • 4,991
  • 3
  • 34
  • 34
  • 1
    In my case I needed to fix some errors with `python manage.py collectstatic ` so `DISABLE_COLLECTSTATIC` would have been a band aid... – citynorman Dec 21 '17 at 20:00
  • 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 ? – Ben2pop Jan 07 '18 at 13:45
  • 1
    Have no idea why this works but this solved my problem so +1. – waqasgard Oct 28 '18 at 07:43
  • @Ben2pop, add `STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')` to your settings.py file, better under `STATIC_URL` – Moaaz Jan 15 '21 at 15:53
  • 1
    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` – Ali Husham Apr 01 '21 at 13:18
  • 3
    What the heck does bower have to do with anything? – blimpse Jun 10 '21 at 19:04
  • 3
    Got error `bash: bower: command not found` – Alexander P Sep 23 '21 at 13:32
42

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.

D. Evans
  • 3,242
  • 22
  • 23
23

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)

Community
  • 1
  • 1
Overdrivr
  • 6,296
  • 5
  • 44
  • 70
  • I have zero errors after doing step 1 but git still won't push? – CountDOOKU Oct 12 '22 at 07:37
  • This is correct, do not disable the command, in my case i just needed to edit the `settings.py` file to point the location of a folder for the static files by adding `STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')` so now when the command get's ran in the server, i get no issues. – jadinerky May 30 '23 at 01:39
7

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

citynorman
  • 4,918
  • 3
  • 38
  • 39
  • 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. – citynorman Feb 05 '18 at 02:37
6

if you use django-heroku library

maybe you forget for put this setting in the bottom of line text settings.py for can possible read all config parameters

import django_heroku

django_heroku.settings(locals())

as like as the documentation:

Usage of Django-Heroku

In settings.py, at the very bottom::

…
# Configure Django App for Heroku.
import django_heroku
django_heroku.settings(locals())

This will automatically configure DATABASE_URL, ALLOWED_HOSTS, WhiteNoise (for static assets), Logging, and Heroku CI for your application.

p.s: sorry for my bad english

Eki Saputra
  • 177
  • 1
  • 7
5

This worked for me:

step 1 - heroku config:set DISABLE_COLLECTSTATIC=1
step 2 - git push heroku master

BetaDev
  • 4,516
  • 3
  • 21
  • 47
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.

Adit_Chheda
  • 67
  • 1
  • 2
4

I face same problem..

Follow this step

  1. heroku config:set DISABLE_COLLECTSTATIC=1
  2. git push heroku master
  3. python manage.py collectstatic
  4. python manage.py test
  5. If any error occurred after running test..check your STATIC_ROOT is correct like this ==> STATIC_ROOT = os.path.join(BASE_DIR, 'static').
  6. After run collectstatic command check all static files are store in static directory for your root dir. level(manage.py dir. level)...
  7. heroku run python manage.py collectstatic.
  8. heroku run python manage.py migrate
  9. heroku config:unset DISABLE_COLLECTSTATIC (for future use).
tomerpacific
  • 4,704
  • 13
  • 34
  • 52
Pradip Kachhadiya
  • 2,067
  • 10
  • 28
2

Heroku had made a document with suggestions on how to handle this https://devcenter.heroku.com/articles/django-assets

add to settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

make a directory in the root of your project called staticfiles, put a favicon or something in there, just make sure git tracks it. Then the collectstatic command should finish on heroku.

Zev Eisenberg
  • 8,080
  • 5
  • 38
  • 82
Harry Moreno
  • 10,231
  • 7
  • 64
  • 116
1

Ran to that issue after trying to deploy an app again. The problem got cured after I specified these commands:

$ heroku config:set SECRET_KEY="*secret_key*"
$ heroku config:set DEBUG_VALUE="True"
$ heroku config:set EMAIL_USER="*user-email*"
$ heroku config:set EMAIL_PASS="*pass*"

These variables in settings.py were invoked with local environment variables, which heroku didn't have on its environment, hence the error.

Sandpaw
  • 23
  • 7
  • 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. – The Sammie Jul 30 '21 at 15:56
  • Wouldn't this enable DEBUG in production which is a big no-no? It should be set to false. – wjh18 Aug 13 '21 at 02:53
0

It seems to me that it's having problems creating that blogproject/static folder. I see you have a static folder inside your blog app, but it should be up one level in your blogproject folder.

Try creating a static folder inside your blogproject folder and that error should go away.

awwester
  • 9,623
  • 13
  • 45
  • 72
  • 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. – Stefano De Rosso Apr 16 '16 at 16:16
0

Today, not all of the requirements came in properly with $ pipenv install django from the heroku-django-template and $ pip install -r requirements.txt.

The latest version of the template includes a /static folder with a humans.txt, so the previous solution is likely not the proplem

Try running $ pipenv install whitenoise and then $ pip freeze > requirements.txt.

If that works, I would recommend $ pip install psycopg2 --ignore-installed and $ pip freeze > requirements.txt as well, otherwise you will similarly have problems migrating.

0

I faced the same issue while deploying my app. I realized I had updated my pip version, installed few plugins but forgot to create a fresh requirements.txt file.

Run pip freeze > requirements.txt in your terminal
Run python manage.py collectstatic
Now push the code to github and deploy to heroku server

Hope this helps if that is the case

Libin Thomas
  • 829
  • 9
  • 18
0

insert this line of code to your setting.py file.

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

Joshua Johns
  • 340
  • 1
  • 3
  • 10
0

In my case was an error almost like described above, after push-ing that resulted in errors, I set the SECRET_KEY "heroku config:set SECRET_KEY='*************************'", git push heroku main (again) , heroku run python manage.py migrate , heroku run python manage.py createsuperuser .. and everything , heroku open and it worked :)

Azuuu
  • 853
  • 8
  • 17
wetal
  • 1
  • 3
0

removing STATICFILES_DIRS worked in my case

Ashok
  • 11
  • 1
0
heroku config:set DISABLE_COLLECTSTATIC=1 --app #yourappname

Just run the command

shailu
  • 190
  • 1
  • 10
0

This problem occurs because Heroku tries to run manage.py. While executing manage.py we have to write like python manage.py 'some_command'

But Heroku tries it as python manage.py --noinput

So in this case we can make changes to our manage.py file: Initialy it looks like this:

 #!/usr/bin/env python
 """Django's command-line utility for administrative tasks."""
 import os
 import sys

 def main():
     """Run administrative tasks."""
     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 
'your_project.settings')
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:
         raise ImportError(
             "Couldn't import Django. Are you sure it's installed and "
             "available on your PYTHONPATH environment variable? Did you "
             "forget to activate a virtual environment?"
         ) from exc

     execute_from_command_line(sys.argv) # just put this in try block

 if __name__ == '__main__':
     main()

So we change our main.py to:

 #!/usr/bin/env python
 """Django's command-line utility for administrative tasks."""
 import os
 import sys

 def main():
     """Run administrative tasks."""
     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 
'your_project.settings')
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:
         raise ImportError(
             "Couldn't import Django. Are you sure it's installed and "
             "available on your PYTHONPATH environment variable? Did you "
             "forget to activate a virtual environment?"
         ) from exc
     try:
          execute_from_command_line(sys.argv) # just put this in try block
     except:
          pass

 if __name__ == '__main__':
     main()
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Adi bhai
  • 23
  • 4
0

If you used .env files and python-decouple you'll have to define the environmental variables in Heroku app settings > Config Vars. Otherwise collectstatic won't work.

Avishka Dambawinna
  • 1,180
  • 1
  • 13
  • 29
0

After testing everything that was posted on this thread, here's what worked for me:

  • Keep the Heroku environment variable DISABLE_COLLECTSTATIC set to 0, as it won't really solve the issue, but just mask it and mess with your site's assets
  • When using django_heroku lib on the settings file, include the argument "staticfiles=False", like this: django_heroku.settings(locals(), staticfiles=False)
  • The STATIC_ROOT variable on settings.py should be set as STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles'), being BASE_DIR set as BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))). This is described on Heroku's django-assets doc
  • After doing all that, run a python manage.py migrateon Heroku CLI and you should see a message about assets downloaded.

Before making it to actually work, the collectstatic command python manage.py collectstatic on Heroku CLI was giving a correct output, so be aware that you may get no errors with this command, but still have something wrong going on.

LucianoBAF
  • 189
  • 2
  • 6
0

Well in my research about this error, I found out that by just adding.

DISABLE_COLLECTSTATIC = 1

in the env variables in Heroku resolved the error

kaybrian
  • 61
  • 1
  • 6