Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heroku/Django deploy: why am I getting an error 500 with successful deploy and static collection?

Tags:

django

heroku

I've been struggling to deploy my first Django site on Heroku for months. I'm getting successful builds with git push heroku master and successfully collecting the static files using heroku run python manage.py collectstatic --noinput, but I can't get the site to serve without an error 500 when DEBUG = config('DEBUG', default=False, cast=bool). The site does work when DEBUG is set to True (though I'm going to have to figure out making the database work). I think my allowed hosts are set correctly. All of the answers I can find on SO don't quite solve my issue.

I added the logging from this answer which gives me a little more information in the logs, but I'm not understanding why the staticfiles aren't available when I've been able to successfully collect them?

2018-12-09T16:24:38.181428+00:00 heroku[web.1]: State changed from starting to up
2018-12-09T16:24:39.173376+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/whitenoise/base.py:104: UserWarning: No directory at: /app/staticfiles/
2018-12-09T16:24:39.173419+00:00 app[web.1]: warnings.warn(u'No directory at: {}'.format(root))
2018-12-09T16:24:39.173421+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/whitenoise/base.py:104: UserWarning: No directory at: /app/staticfiles/
2018-12-09T16:24:39.173423+00:00 app[web.1]: warnings.warn(u'No directory at: {}'.format(root))

I'm obviously missing a lot, any guidance would be most appreciated.

Editing to add:

settings.py

import os
import dj_database_url
from decouple import config

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=False, cast=bool)

ALLOWED_HOSTS = [
    'localhost',
    '127.0.0.1',
    'tallymusic.herokuapp.com',
    '.tallymusic.net'
]

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # user-created apps
    'concerts',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'tallymusic.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        '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 = 'tallymusic.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
    'default': dj_database_url.config(
        default=config('DATABASE_URL')
    )
}
""" # dev
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
"""

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'EST'
USE_I18N = True
USE_L10N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/assets/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'assets'),
    os.path.join(BASE_DIR, 'assets/css'),
    os.path.join(BASE_DIR, 'assets/images'),
    os.path.join(BASE_DIR, 'assets/js'),
)

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# https://stackoverflow.com/questions/15128135/setting-debug-false-causes-500-error
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt' : "%d/%b/%Y %H:%M:%S"
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'mysite.log',
            'formatter': 'verbose'
        },
    },
    'loggers': {
        'django': {
            'handlers':['file'],
            'propagate': True,
            'level':'DEBUG',
        },
        'MYAPP': {
            'handlers': ['file'],
            'level': 'DEBUG',
        },
    }
}

More logs

2018-12-09T16:24:14.000000+00:00 app[api]: Build started by user ME
2018-12-09T16:24:29.581094+00:00 heroku[web.1]: Restarting
2018-12-09T16:24:29.581759+00:00 heroku[web.1]: State changed from up to starting
2018-12-09T16:24:30.254016+00:00 app[web.1]: [2018-12-09 16:24:30 +0000] [4] [INFO] Handling signal: term
2018-12-09T16:24:30.254190+00:00 app[web.1]: [2018-12-09 11:24:30 +0000] [11] [INFO] Worker exiting (pid: 11)
2018-12-09T16:24:30.255609+00:00 app[web.1]: [2018-12-09 11:24:30 +0000] [12] [INFO] Worker exiting (pid: 12)
2018-12-09T16:24:30.297433+00:00 app[web.1]: [2018-12-09 16:24:30 +0000] [4] [INFO] Shutting down: Master
2018-12-09T16:24:30.245505+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2018-12-09T16:24:30.366997+00:00 heroku[web.1]: Process exited with status 0
2018-12-09T16:24:29.201161+00:00 app[api]: Deploy eff240d7 by user ME
2018-12-09T16:24:29.201161+00:00 app[api]: Release v23 created by user ME
2018-12-09T16:24:34.427399+00:00 heroku[web.1]: Starting process with command `gunicorn tallymusic.wsgi --log-file -`
2018-12-09T16:24:36.000000+00:00 app[api]: Build succeeded
2018-12-09T16:24:37.293769+00:00 app[web.1]: [2018-12-09 16:24:37 +0000] [4] [INFO] Starting gunicorn 19.9.0
2018-12-09T16:24:37.294491+00:00 app[web.1]: [2018-12-09 16:24:37 +0000] [4] [INFO] Listening at: http://0.0.0.0:3342 (4)
2018-12-09T16:24:37.296193+00:00 app[web.1]: [2018-12-09 16:24:37 +0000] [4] [INFO] Using worker: sync
2018-12-09T16:24:37.315139+00:00 app[web.1]: [2018-12-09 16:24:37 +0000] [11] [INFO] Booting worker with pid: 11
2018-12-09T16:24:37.380085+00:00 app[web.1]: [2018-12-09 16:24:37 +0000] [12] [INFO] Booting worker with pid: 12
2018-12-09T16:24:38.181428+00:00 heroku[web.1]: State changed from starting to up
2018-12-09T16:24:39.173376+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/whitenoise/base.py:104: UserWarning: No directory at: /app/staticfiles/
2018-12-09T16:24:39.173419+00:00 app[web.1]: warnings.warn(u'No directory at: {}'.format(root))
2018-12-09T16:24:39.173421+00:00 app[web.1]: /app/.heroku/python/lib/python2.7/site-packages/whitenoise/base.py:104: UserWarning: No directory at: /app/staticfiles/
2018-12-09T16:24:39.173423+00:00 app[web.1]: warnings.warn(u'No directory at: {}'.format(root))
like image 519
Danny Avatar asked Dec 09 '18 16:12

Danny


People also ask

Does Heroku support static files?

Storing static files elsewhere is crucial for Heroku apps since dynos have an ephemeral filesystem. Whenever you replace a dyno or when it restarts, which happens daily, all files that aren't part of your application's slug are lost. Use a storage solution like S3 to offload the storage of static files from your app.

Can we deploy Django project in Heroku?

When you deploy to Heroku, the dependencies you specify in your requirements. txt file are automatically installed before app startup. If you're using Django, the collectstatic command also runs automatically during the deployment process.


1 Answers

You most likely have solved the problem, however this is for anyone else who has the problem in the future.

Most sites and people say that you need to update the ALLOWED_HOSTS in settings.py like so: ['www.beta800.net', '127.0.0.1'] (or ['*'] for a quick test, NOT for production).

For me, this didn't solve the problem, though it is important to update ALLOWED_HOSTS either way. My problem was that my app was missing the static files folders. If the logging shows you an error similar to this: UserWarning: No directory at:/app/static/ warnings.warn(u'No directory at: {}'.format(root)) this is the problem in your app as well. If that is the case, follow these steps:

  1. Locally, change the DEBUG property in settings.py to True.

  2. Make sure you have the following properties set in settings.py:

# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'

# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
  1. Locally, add a folder named static to the root folder.

  2. Locally, run python manage.py collectstatic. This should create another folder in your app's root folder called staticfiles.

  3. Now you can set the DEBUG property in settings.py to False and deploy your app.

like image 141
E. Epstein Avatar answered Oct 21 '22 10:10

E. Epstein