Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django project with gunicorn server on Heroku does not serve static files

My Django 1.3 project serves the static files on a development server but with the gunicorn server static files are not served. I followed the steps of this Heroku guide.

When I used the contents of my procfile like in the guide ( web: gunicorn myproject_django.wsgi -b 0.0.0.0:$PORT) my project was not recognised by Heroku.

Then I changed that Procfile to this:

web: python myproject_django/manage.py run_gunicorn -b 0.0.0.0:$PORT -w 3

Now my app runs except for the static files(css not active nor images).

My project tree:

.
├── Procfile
├── myproject_django
│   ├── core
│   │   ├── admin.py
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── static
│   │   │   ├── css
│   │   │   │   ├── base.css
│   │   │   │   ├── layout.css
│   │   │   │   
│   │   │   └── media
│   │   │       ├── pek.ico
│   │   │       ├── pek.png
│   │   │       ├── pek_symbol.png
│   │   ├── tests.py
│   │   └── views.py
│   ├── __init__.py
│   ├── manage.py
│   ├── settings.py
│   ├── templates
│   │   └── core
│   │       ├── home.html
│   │       └── install.html
│   └── urls.py
└── requirements.txt

Potentially relevant parts of settings.py

MEDIA_ROOT = ''

MEDIA_URL = '/static/media'

STATIC_ROOT = ''

STATIC_URL = '/static/'

ADMIN_MEDIA_PREFIX = '/static/admin/'

STATICFILES_DIRS = (
    os.path.abspath(__file__)+'/..'+'/myproject_django/core/static', 
)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)


INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core',
    'gunicorn',
    'django.contrib.admin',
)

Edit

I adjusted the following things after Francis Yaconiello's entry:

In settings.py

STATIC_ROOT = os.path.join(os.getcwd(),'core/static')
STATICFILES_DIRS = ( os.path.abspath(__file__)+'/..'+'/core/static', )

In gitignore:

staticfiles/*

Then commited. And finally ran heroku run python myproject_django/manage.py collectstatic.

But static files are still not served when I check the webpage. Given my directory tree why didn't these changes work?

Edit2

I still don't see my static files. When I click on an image while DEBUG=True I get this:

Request URL: http://myproject.herokuapp.com/static/media/pek.png

Tree (Note that the staticfiles dir is empty)

.
├── Procfile
├── myproject_django
│   ├── admin
│   ├── core
│   │   ├── admin.py
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── static
│   │   │   ├── css
│   │   │   │   ├── base.css
│   │   │   │   ├── layout.css
│   │   │   └── media
|   |   |       ├── pek.ico
|   │   │       ├── pek.png
|   │   │       ├── pek_symbol.png
│   │   ├── tests.py
│   │   ├── views.py
│   ├── __init__.py
│   ├── manage.py
│   ├── settings.py
│   ├── staticfiles
│   ├── templates
│   │   └── core
│   │       ├── 404.html
│   │       ├── 500.html
│   │       ├── home.html
│   │       └── install.html
│   ├── urls.py
└── requirements.txt

In settings.py

PROJECT_PATH = os.path.dirname(os.path.abspath(__file__))
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'static/media')
STATIC_ROOT = os.path.join(PROJECT_PATH,'staticfiles')
STATICFILES_DIRS = (
    os.path.join(PROJECT_PATH, 'core/static'),
)
like image 307
Bentley4 Avatar asked Aug 16 '12 19:08

Bentley4


People also ask

Does Gunicorn serve static files?

Gunicorn is meant to serve dynamic content, it should not be used to serve static files.

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.

How do I get static on Heroku?

Collectstatic during builds When a Django application is deployed to Heroku, $ python manage.py collectstatic --noinput is run automatically during the build. A build will fail if the collectstatic step is not successful.

How does Django manage static files?

Configuring static filesMake sure that django.contrib.staticfiles is included in your INSTALLED_APPS . In your templates, use the static template tag to build the URL for the given relative path using the configured STATICFILES_STORAGE . Store your static files in a folder called static in your app.


1 Answers

Specify your STATIC_ROOT

I generally set it to :

import os
STATIC_ROOT = os.path.join(os.getcwd(), "staticfiles")

create that directory in your project

mkdir staticfiles

make sure that the contents of staticfiles is not git tracked

nano .gitignore

add

staticfiles/*

then commit it and push to heroku.

lastly,

heroku run python manage.py collectstatic

EDIT

STATIC_ROOT = os.path.join(os.getcwd(),'core/static')
STATICFILES_DIRS = ( os.path.abspath(__file__)+'/..'+'/core/static', )

These two settings cannot be the same thing.

STATICFILES_DIR is OK, if redundant your STATICFILES_FINDERS already is telling it to find staticfiles in the static directory of each app with this: 'django.contrib.staticfiles.finders.AppDirectoriesFinder',

The point of STATIC_ROOT is to provide a new directory completely separate from your project that you can serve with a third party server like nginx. Which is why you created that directory staticfiles:

STATIC_ROOT = os.path.join(os.getcwd(),'staticfiles')

ANOTHER EDIT

workaround for ephemeral filesystem

Each dyno gets its own ephemeral filesystem, with a fresh copy of the most recently deployed code. During the dyno’s lifetime its running processes can use the filesystem as a temporary scratchpad, but no files that are written are visible to processes in any other dyno and any files written will be discarded the moment the dyno is stopped or restarted.

which means that as long as you collectstatic on each dyno instance during web startup, you won't have any issues.

web: python myproject_django/manage.py collectstatic --noinput; python myproject_django/manage.py run_gunicorn -b 0.0.0.0:$PORT -w 3

That said, I currently use S3 and django storages http://django-storages.readthedocs.org/en/latest/index.html. Its fairly easy (and cheap) to get this going.

like image 176
Francis Yaconiello Avatar answered Oct 09 '22 09:10

Francis Yaconiello