Turn off caching of static files in Django development server

后端 未结 9 2187
灰色年华
灰色年华 2020-11-30 04:52

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:

<
相关标签:
9条回答
  • 2020-11-30 05:05

    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')
    
    0 讨论(0)
  • 2020-11-30 05:07

    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.

    0 讨论(0)
  • 2020-11-30 05:15

    In newer versions of Django a very simple solution is modify the project urls like so:

    from django.conf.urls.static import static
    from django.contrib.staticfiles.views import serve
    from django.views.decorators.cache import cache_control
    from django.conf import settings
    
    # YOUR urlpatterns here... 
    
    if settings.DEBUG:
        urlpatterns += static(settings.STATIC_URL, view=cache_control(no_cache=True, must_revalidate=True)(serve))
    

    I arrived at this by looking at how staticfiles modifies the urls automatically and just adding a view decorator. I really don't understand why this isn't the default as this is for development ONLY. The view is able to properly handle a "If-Modified-Since" HTTP header so a request is always made but contents are only transferred on changes (judged by looking at the modification timestamp on the file).

    For this to work you must add --nostatic when using runserver, otherwise the above changes are simply ignored.

    IMPORTANT EDIT: What I had before didn't work because I wasn't using --nostatic and the never_cache decorator also included no-store which meant unchanged files were always being re-transferred instead of returning 304 Not Modified

    0 讨论(0)
  • 2020-11-30 05:20

    @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',
        )
    
    0 讨论(0)
  • 2020-11-30 05:21

    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)
    
    0 讨论(0)
  • 2020-11-30 05:21

    It's so simple if you are using Django 2.0+

    Step-1 : Make 'django.contrib.staticfiles' as comment in settings.py(Project level)

    INSTALLED_APPS = [

    # 'django.contrib.staticfiles',
    

    ]

    Step-2 : Import followings in urls.py (Project level)

         from django.conf.urls.static import static
    
         from django.contrib.staticfiles.views import serve
    
         from django.views.decorators.cache import never_cache
    
         from . import settings
    

    Step-3 : Add following line in urls.py(project level) after urlpatterns

    urlpatterns = [
    
    ]
    
    if settings.DEBUG:
    
        urlpatterns += static(settings.STATIC_URL, view=never_cache(serve))
    

    Make sure that STATIC_URL is declared in your settings.py

    STATIC_URL = '/static/'
    
    0 讨论(0)
提交回复
热议问题