Turn off caching of static files in Django development server

Is there an easy way to turn off caching of static files in Django's development server?

I'm starting the server with the standard command:

$ python manage.py runserver

I've got settings.py configured to serve up static files from the /static directory of my Django project. I've also got a middleware class that sets the Cache-Control header to must-revalidate, no-cache for development, but that only seems to affect URLs that are not in my /static directory.


@Erik Forsberg's answer worked for me. Here's what I had to do:

  • Comment out the staticfiles app from INSTALLED_APPS in settings.py:

    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        #'django.contrib.staticfiles',
    )
    
  • Leave my STATIC_URL variable set in settings.py:

    STATIC_URL = '/static/'
    
  • Add an entry to my project's base urls.py:

    # static files w/ no-cache headers
    url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
        {'document_root': settings.STATIC_ROOT}),
    

Note that I'm also setting the Cache-Control headers in a middleware class nocache.py:

class NoCache(object):
    def process_response(self, request, response):
        """
        set the "Cache-Control" header to "must-revalidate, no-cache"
        """
        if request.path.startswith('/static/'):
            response['Cache-Control'] = 'must-revalidate, no-cache'
        return response

And then including that in settings.py:

if DEBUG:
    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'nocache.NoCache',
    )

Django's contrib.staticfiles app automatically serves staticfiles for you by overriding the runserver command. With this configuration you can't control the way it serves the static files.

You can prevent the staticfiles app from serving the static files by adding the --nostatic option to the runserver command:

./manage.py runserver --nostatic

Then you can write an url config to manually serve the static files with headers that prevent the browser from caching the response:

from django.conf import settings
from django.contrib.staticfiles.views import serve as serve_static
from django.views.decorators.cache import never_cache

urlpatterns = patterns('', )

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^static/(?P<path>.*)$', never_cache(serve_static)),
    )

If you want your manage.py runserver command to have the --nostatic option on by default, you can put this in your manage.py:

if '--nostatic' not in sys.argv:
    sys.argv.append('--nostatic')

Assuming you're using django.views.static.serve, it doesn't look like it - but writing your own view that just calls django.views.static.serve, adding the Cache-Control header should be rather easy.


My very simple solution:

from django.contrib.staticfiles.views import serve
from django.views.decorators.cache import never_cache

static_view = never_cache(serve)
urlpatterns += static_view(settings.MEDIA_URL,
                           document_root=settings.MEDIA_ROOT)

Use whitenoise. There's a lot of issues with the static file serving in runserver and they're all already fixed in whitenoise. It's also WAY faster.

They've talked about just replacing the built-in static serving with it, but no one has gotten around to it yet.

Steps to use it in development...

Install with pip install whitenoise

Add the following to the end of settings.py:

if DEBUG:
    MIDDLEWARE = [
        'whitenoise.middleware.WhiteNoiseMiddleware',
    ] + MIDDLEWARE
    INSTALLED_APPS = [
        'whitenoise.runserver_nostatic',
    ] + INSTALLED_APPS