1

I'm stuck due to an evergreen issue, static files not served. Conversely the files placed in the MEDIA_ROOT subtree get served correctly under MEDIA_URL.

Stripped settings.py:

DEBUG = True
STATIC_URL = '/static/'
STATIC_ROOT = '/home/foo/devel/static'
MEDIA_URL = '/media/'
MEDIA_ROOT = '/home/foo/devel/media'
# the following is deprecated but is it seems grappelly requires it
ADMIN_MEDIA_PREFIX = STATIC_URL + "grappelli/"
STATIC_FILES = ()
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

To create the project I did:

$ cd /home/foo/devel/
$ virtualenv testdrive
$ . bin/activate; pip install django; cd testdrive
$ django-admin.py fbtest

and got this directory tree (stripped):

. <-- /home/foo/devel/
├── bin
├── fbtest
│   └── fbtest
│       ├── media
│       │   └── foo.jpg
│       ├── static
│       └────── foo.jpg
├── include
└── lib

Files under STATIC_URL should be served automatically by Django staticfiles (not in my case), while other files have to be handled manually. So I appended these lines to urls.py:

import settings
if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL.lstrip("/"),
            'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
    )

Accessing http://host/media/filebrowser/foo.jpg works, while http://host/static/foo.jpg gives error 404. Why?

Community
  • 1
  • 1
Paolo
  • 20,112
  • 21
  • 72
  • 113

3 Answers3

6

Files under STATIC_URL should be served automatically by Django staticfiles (not in my case), while other files have to be handled manually.

That's incorrect. Django never serves STATIC_ROOT ever -- not even in development. What it does do is make files in each app's "static" directory and files in any directory specified in STATICFILES_DIRS available at STATIC_URL. You don't actually manually put anything in STATIC_ROOT ever; in fact, in development, you shouldn't even have the directory there. Put simply, STATIC_ROOT is only a dumping ground for your static files in production when you run the collectstatic management command.

In development, all static files should go into someapp/static, where "someapp" is the app they apply to. In the case that the files apply to the project as a whole, a global CSS file for example, you need to create an entirely different directory (i.e. not the same as STATIC_ROOT or MEDIA_ROOT) and then add that directory to STATICFILES_DIRS. For example, I normally call mine "assets", so:

STATICFILES_DIRS = (
    os.path.join(os.path.dirname(__file__), 'assets'),
)
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • +1 Thanks for the great explanation, now things are even more clear. – Paolo Jun 12 '12 at 21:44
  • @Chris Pratt : How do you refer to an app that is in `someapp/static`? For me, `STATIC_URL` can only reach files available in `STATIC_ROOT` (Django 1.3). – Dave Jul 16 '12 at 22:54
  • @Mr.Dave: is this in development or production. In development, remove the `STATIC_ROOT` directory completely. I've noticed Django tends to serve files from there in development *if* it exists, instead of actually referencing all the app's static directories and anything in `STATICFILES_DIRS`. In production, just run `collectstatic` to have everything copied there, and then serve that directory with your web server. – Chris Pratt Jul 18 '12 at 18:31
  • @ChrisPratt: Thanks, I think that was causing the issue! – Dave Jul 18 '12 at 20:58
1

It was a silly error. I forgot to add fbtest to INSTALLED_APPS, so the static file machinery didn't manage static files for this app.

Paolo
  • 20,112
  • 21
  • 72
  • 113
0

This problem is realy evergreen... Some hints:

TEMPLATE_CONTEXT_PROCESSORS = (
    # ...
    'django.core.context_processors.static',
    # ...
)

INSTALLED_APPS = (
    # ...
    'django.contrib.staticfiles',
    # ... 
)

My settings for django 1.4 (no grappelli):

urls.py

if settings.DEBUG:
    urlpatterns = patterns('',

        url(r'^%s(?P<path>.*)$' % settings.STATIC_URL.lstrip('/'), 'django.views.static.serve',
            {'document_root': settings.STATIC_ROOT, "show_indexes": True}),

        url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL.lstrip('/'), 'django.views.static.serve',
            {'document_root': settings.MEDIA_ROOT, "show_indexes": True}),

    ) + urlpatterns

settings.py

MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
MEDIA_URL = '/media/'
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/static/admin/'


TEMPLATE_CONTEXT_PROCESSORS = (
    # ...
    'django.core.context_processors.static',
    # ...
)

INSTALLED_APPS = (
    # ...
    # 'django.contrib.staticfiles',
    # ...
)
Dingo
  • 2,656
  • 1
  • 19
  • 16
  • Thanks. _1._ I tried but didn't help. _2._ Neither adding `show_indexes: True` to the dictionary. _3._ YES, virtualenv creates a `local` directory containing these links: `bin -> /home/foo/devel/testdrive/bin`, `include -> /home/foo/devel/testdrive/include` and `lib -> /home/foo/devel/testdrive/lib`. _4._ Sorry I don't know how to use --adminmedia option. – Paolo Jun 12 '12 at 20:51
  • python manage.py runserver --adminmedia=../path-to-grappelli/grappelli/static/grappelli – Dingo Jun 12 '12 at 20:57
  • adminmedia is base djago command... [=>docs](https://docs.djangoproject.com/en/1.2/ref/django-admin/#django-admin-option---adminmedia) – Dingo Jun 12 '12 at 21:03
  • try to set MEDIA_ROOT = '/home/foo/devel/fbtest/fbtest/media' – Dingo Jun 12 '12 at 21:05
  • Setting MEDIA_ROOT to that value doesn't fix the /static/ problem and breaks the /media/ serving, which previously worked. Let me investigate about the missing --adminmedia option... – Paolo Jun 12 '12 at 21:09
  • The docs for Django 1.4 [cites --adminmedia](https://docs.djangoproject.com/en/1.4/ref/django-admin/#django-admin-option---adminmedia), but `python manage.py help runserver` doesn't list the option. So I assume it is not available in 1.4. – Paolo Jun 12 '12 at 21:29
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12467/discussion-between-guandalino-and-dingo) – Paolo Jun 12 '12 at 21:54