简体   繁体   中英

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'),
)

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.

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}),
)

ps For STATIC_URL = '/static/'

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

I ran into the same problem; it seems you need these three settings in particular:

  1. 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.

  2. 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.

  3. 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 !

我在这里找到解决我在heroku上使用Django的所有问题的好方法

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM