Reputation: 11038
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',
)
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?
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'),
)
Upvotes: 10
Views: 5884
Reputation: 1
I found here good way to resolve all my problems with Django on heroku
Upvotes: 0
Reputation: 9653
I ran into the same problem; it seems you need these three settings in particular:
STATIC_ROOT
must be defined in your settings.py
, for example:
STATIC_ROOT = os.path.join(PROJECT_PATH, 'served/static/')
Where PROJECT_PATH
is your project root (in your case, the absolute path to the myproject_django
directory.
Similarly, STATIC_URL
must also be set (Django will throw an ImproperlyConfigured error anyway, if you don't). Your current setting of '/static/'
is fine.
In your root urls.py
, configure the static urls:
from django.conf import settings
from django.conf.urls.static import static
...
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Finally, run python manage.py collectstatic
; this will copy all the files from /path/to/site-packages/django/contrib/admin/static/admin/
to /served/static/
. (You can read more about how Django serves static files here).
Now when you run foreman start
, you should see the admin with styling.
Don't forget to add served/static/
to your .gitignore
!
Upvotes: 1
Reputation: 301347
Use the run_collectstatic
script which run as part of the post_compile
provided by heroku-django-cookbook. It makes use of the post_compile
hook provided by the Heroku python buildpack
Upvotes: 1
Reputation: 747
There is one solution.
In urls.py add:
from django.conf import settings
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
p.s. For STATIC_URL = '/static/'
Upvotes: 4
Reputation: 10939
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
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')
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.
Upvotes: 5