10

I know this question was asked many times, but none of the answers i found and tried helped me.

Those are my static files settings:

STATIC_ROOT = os.path.abspath(SETTINGS_PATH+'/staticfiles/')

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/staticfiles/'

# Additional locations of static files
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    os.path.join(os.path.dirname(__file__), 'static'),
    )

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
) 

And in myapp/urls.py:

from django.conf.urls import patterns, include, url
from django.conf import settings
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

admin.autodiscover()

urlpatterns = patterns('',
    # urls
)

urlpatterns += staticfiles_urlpatterns()

Collectstatic copies all files to staticfiles/ as it should and i get 404 on all static files.

I also tried this in urls.py:

if not settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^staticfiles/(?P<path>.*)$', 'django.views.static.serve',
            {'document_root': settings.STATIC_ROOT}),
    )

This gives me following kind of errors:

Resource interpreted as Stylesheet but transferred with MIME type text/html:  "http://localhost:8000/?next=/staticfiles/css/bootstrap.css". localhost:11
Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8000/?next=/staticfiles/css/style.css". localhost:12
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8000/?next=/staticfiles/js/bootstrap.js". localhost:79
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:8000/?next=/staticfiles/js/login.js". 

I can't see what's wrong with my settings. Any ideas are most welcome.

Neara
  • 3,693
  • 7
  • 29
  • 40
  • the mime you're getting may refer to a 404 page for a css/script not served at all (thus you expect a stylesheet, but you get an actual 404 page). do you have permissions over your static folders? are you under an htaccess or similar? – Samuele Mattiuzzo Dec 10 '12 at 13:37
  • looking at the error it looks like your static requests are being redirected to a login page. try browsing to one of them in your browser. is some (other, protected) view matching the urls? – second Dec 10 '12 at 13:47
  • ls -la shows drwxr-xr-x. On my pc im not under htaccess, not that i know of. and on production, its on Heroku. – Neara Dec 10 '12 at 13:48
  • @second I indeed added a middleware to insure LoginRequired for all urls atm, except for login page. but signing in doesnt help. And i didn't have any problem with serving static files while debug=true. – Neara Dec 10 '12 at 13:52

7 Answers7

16

as you can see in the warning box in the docs, in production (i.e. with debug=False) you should be using your web server to serve static files, not django. For that reason, staticfiles will refuse to serve your assets if debug=False.

second
  • 28,029
  • 7
  • 75
  • 76
  • 2
    I set debug=false to recreate a problem i have on prod server. This app is deployed on Heroku. And i have same problem there, but i use second version of urls.py. Everything worked for a time, but no more. I intend to use S3 asap, but for now i need it to work w.o. Any ideas how to change the settings to make it work? – Neara Dec 10 '12 at 13:45
  • 1
    +1 Thanks @second - that appear to be my problem here. Preparing for deployment and running locally. Another deployment wrinkle! – winwaed Nov 15 '13 at 21:59
  • Is the other answer by Angel above correct or a workaround? – Saher Ahwal Nov 04 '16 at 21:15
  • i would not use django staticfiles in production. if you need a pure python solution (e.g. for heroku), consider [whitenoise](http://whitenoise.evans.io/en/stable/django.html) – second Nov 05 '16 at 23:30
  • Minor rant at Django: I don't want to use staticfiles in production, I just want to use it development without having the debug error pages etc. – OrangeDog Dec 08 '17 at 10:57
15

in settings.py::

if DEBUG: 
   STATIC_ROOT = os.path.join(BASE_DIR, '/static')
else:
   STATIC_ROOT = os.path.join(BASE_DIR, 'static') 

and in urls.py add

import django.views.static
urlpatterns += [
   url(r'^static/(?P<path>.*)$', django.views.static.serve, {'document_root': settings.STATIC_ROOT, 'show_indexes': settings.DEBUG})
]
Community
  • 1
  • 1
Angel Sullon
  • 151
  • 1
  • 3
  • Hey so the django folks say that the original method when debug is true is "This method is grossly inefficient and probably insecure, so it is unsuitable for production." here: https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production. Is what you are doing a workaround or the right thing to do? – Saher Ahwal Nov 04 '16 at 21:14
  • Why I am getting this error? `Directory indexes are not allowed here` – Mehran Nouri Jun 04 '19 at 14:47
  • for people using Django ver 2.1 + `STATIC_ROOT = 'static'` – wishmaster Nov 22 '20 at 14:11
7

I'm using the code below in my root urls.py. You need to set FORCE_SERVE_STATIC to True in settings file if you want static and media to be served by django development server. And don't forget to run collectstatic command to update your static files.

from django.conf.urls.static import static
from django.conf import settings

<...>

if settings.DEBUG:
    urlpatterns += static(
        settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
elif getattr(settings, 'FORCE_SERVE_STATIC', False):
    settings.DEBUG = True
    urlpatterns += static(
        settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(
        settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    settings.DEBUG = False
simplylizz
  • 1,686
  • 14
  • 28
7

This is a late answer but may be this will help someone. There is an extra option to be used with runserver command which force Django to serve static files even when DEBUG=False

python manage.py runserver --insecure

Django docs ref: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#cmdoption-runserver-insecure

Lal
  • 1,599
  • 15
  • 18
  • 2
    This is the right solution for anyone wishing just to develop django site but make it run a little bit faster. It's the right way also because it is only a flag, and would/should probably not be moved on to production environment. – rubmz Jun 13 '19 at 22:32
  • Was --insecure deprecated? I receive this error: manage.py runserver: error: unrecognized arguments: --insecure – prsnr Dec 22 '22 at 08:09
1

With debug turned off Django won't serve static files for you any more . Your production web server (Apache or Heroku or Pythonanywhere or something like this) should take care of that.

1

In your urls.py file:

add this line

from django.views.static import serve

add those two urls in urlpatterns:

url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}),
url(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}),
Thusitha Deepal
  • 1,392
  • 12
  • 19
0
from django.views.static import serve
from django.conf import settings

if not settings.DEBUG:
    urlpatterns += re_path(
        r'^static/(?P<path>.*)$', serve, dict(document_root=settings.STATIC_ROOT)),

Note:

django.conf.urls.url() is deprecated in favor of django.urls.re_path().

def url(regex, view, kwargs=None, name=None):
    warnings.warn(
        'django.conf.urls.url() is deprecated in favor of '
        'django.urls.re_path().',
        RemovedInDjango40Warning,
        stacklevel=2,
    )
    return re_path(regex, view, kwargs, name)
BaiJiFeiLong
  • 3,716
  • 1
  • 30
  • 28