41

I've having a little issue with Django's staticfiles app.

I have added

'django.contrib.staticfiles',

to my INSTALLED_APPS and have added

STATIC_URL = '/static/'
STATIC_ROOT = '/Users/kevdotbadger/django/mylook/static/'

to my settings.py file.

All my static files are located within the STATIC_ROOT folder on my Mac.

Now, within my template I use

{{ STATIC_URL }}

which correctly renders to /static/.

However

{{ STATIC_URL }}css/style.css

result in a 404 error. I'm using the 'runserver' command as the server.

Is there something I'm missing?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dotty
  • 40,405
  • 66
  • 150
  • 195

5 Answers5

119

I implore you to read the howto docs here: http://docs.djangoproject.com/en/dev/howto/static-files/

In short: STATIC_ROOT is only used if you call the collectstatic manangement command. It's not needed to add the directory to the STATICFILES_DIRS setting to serve your static files!

During development (when the automatic serving view is used) staticfiles will automatically look for static files in various locations (because you call its "serve" view with a path to a static file). For this search it'll use the so called "finders" (as defined in the STATICFILES_FINDERS setting).

  1. One of the default finders is the AppDirectoriesFinder, which will look in the "/static/" directory of each of the apps of yours INSTALLED_APPS setting.

  2. Another default finder is the FileSystemFinder, which will look in directories you specify in the STATICFILES_DIRS setting.

BTW, both these search patterns are similar to how template loading works.

The same technique will be used when running the collectstatic command, except that it now will collect the files from the various locations (using the same finders as above), putting the found files into STATIC_ROOT, ready for deployment.

jezdez
  • 1,499
  • 2
  • 8
  • 9
  • 3
    This is the correct answer. STATICFILES_DIRS is specifically used by the staticfiles app. STATIC_ROOT is not. STATIC_ROOT is used to collect all your media into one place for your production environment, from the STATICFILES_DIRS and the static folder of each app if the AppDirectoriesFinder is installed. This bit me hard today, specifically for static media that was particular to the project rather than any app. – Josh Smeaton Mar 20 '11 at 10:22
  • @JoshSmeaton - Whenever we run "python manage.py collectstatic" it collects all the files from STATICFILES_DIRS paths and copies into the the STATIC_ROOT. But i noticed when i run my app, django is reading the files from the STATICFILES_DIRS path, not from the STATIC_ROOT. Is this normal? If then what is the use of this STATIC_ROOT. Simply to hold all the files in one place. or am i doing something wrong? – ASKN May 05 '12 at 13:54
  • 1
    @Ashin, the static files app that serves static files from within django will not serve from static_root, only from the staticfiles_dirs and (if you've got app-static finder enabled) from app-static dirs. Static Root is so you can point a separate webserver at the directory after it has been collected. – Josh Smeaton May 07 '12 at 12:09
  • 2
    Got it. @JoshSmeaton i even noticed when we make DEBUG = False , then the django reads it from the STATIC_ROOT. and when DEBUG = True it reads from the STATICFILES_DIRS path. Your comment on this. – ASKN May 08 '12 at 03:29
  • @Ashin, it's probably how you've configured your urls.py file. You've setup the static urls only for when DEBUG = True. I don't know how you've configured your webserver with STATIC_ROOT. – Josh Smeaton May 08 '12 at 07:02
3

I found a quick and easy workaround to serve project global static files during development:

  • Start a new app that contains your projects static files (e.g. "manage.py startapp static_content")
  • Create a folder named 'static' in that app and put your static files there.
  • Add your new app to the list of installed apps
Markus Lenger
  • 521
  • 5
  • 7
3

If you want just a solution - scroll down to the "Solution".

Overview

I was discovering the same problem yesterday. Here is what I found:

All you need is appropriate static finder, that will find your STATIC_ROOT and all its contents, but there is no such finder. Here are default finders:

  • django.contrib.staticfiles.finders.AppDirectoriesFinder - search installed django applications dirs for 'static' folder, but most of them use obsolete 'media' folders for now.

  • django.contrib.staticfiles.finders.FileSystemFinder - use all dirs mentioned in the STATICFILES_DIRS, but you can't add STATIC_ROOT into it.

  • django.contrib.staticfiles.finders.DefaultStorageFinder - search static in your DEFAULT_FILE_STORAGE which is django.core.files.storage.FileSystemStorage by default and it points to your MEDIA_ROOT

Solution

That's all, no additional choices. There are no choices to use STATIC_ROOT for now (in Django 1.3).
So I've just wrote my own custom finder for these needs:

  • My custom static finder file: finders.py:

    from django.core.files.storage import FileSystemStorage
    from django.contrib.staticfiles.finders import BaseStorageFinder
    from django.conf import settings
    
    class StaticFinder(BaseStorageFinder):
        storage = FileSystemStorage(settings.STATIC_ROOT, settings.STATIC_URL)
    
  • settings.py:

    STATICFILES_FINDERS = (
        'finders.StaticFinder',
    )
    
  • If you want to use it with another finders - I suggest to put them after it inside STATICFILES_FINDERS

And remember: this solution should be used only in development needs and never on production!

Rost
  • 3,602
  • 2
  • 21
  • 21
  • Way too complex! There is already a STATICFILES_DIRS setting which you can add file system paths to. – Josh Smeaton May 11 '11 at 13:26
  • 1
    2 Josh Smeaton: Unfortunately I can't add 'static' into STATICFILES_DIRS - it will be ignored. But I want to use 'static' for my dev server – Rost Jul 11 '11 at 13:22
  • 4
    The reason they've designed it to ignore the 'static' folder is because it isn't meant to be used as a place to manually put your static content. The static dir is where all the various static files get copied to for DEPLOYMENT. Just create a a different directory that you dump top level static files in, and leave the static root folder for what it is. A collection point. – Josh Smeaton Jul 11 '11 at 23:30
  • 4
    WTF! The default storage backend (https://github.com/django/django/blob/abc29a04a1db768207c04e687376b961167cc6da/django/contrib/staticfiles/storage.py#L21-42) which is used by the collectstatic management command TO COLLECT files, is exactly like this proposed "solution". What you will get is a BROKEN state, in which files will be recursively copied. DON'T DO THAT. – jezdez Aug 17 '11 at 10:13
  • No you may not. It's unsupported, you're on your own if you do that. – jezdez Sep 14 '11 at 11:47
  • kottenator already warns to ONLY use this in development. And I love this solution! Because we don't use the "collectstatic" command - ever. I think Django should not force this structure. Thanks kottenator :-) – Simon Steinberger Oct 06 '14 at 15:09
1

First of all, make sure that you have static serve enabled in your urls.py FOR DEVELOPMENT ONLY.

Also, you may have an extra slash in there. If your STATIC_URL == '/static/', then

{{ STATIC_URL }}/css/style.css should be {{ STATIC_URL }}css/style.css.

C. Alan Zoppa
  • 823
  • 8
  • 11
1
STATIC_ROOT = '/home/ws/be/bla/'
STATICFILES_DIRS = ('/home/ws/be/static/',)
STATIC_URL = '/static/'

This works for me. STATIC_ROOT must differ from STATICFILES_DIRS (Django version 1.4 pre-alpha SVN-16436)

maruusos82
  • 85
  • 1
  • 6