关闭Django开发服务器中的静态文件缓存

时间:2011-08-10 15:47:03

标签: python django

在Django的开发服务器中是否有一种简单的方法可以关闭静态文件的缓存?

我正在使用标准命令启动服务器:

$ python manage.py runserver

我已将settings.py配置为从我的Django项目的/static目录中提供静态文件。我还有一个中间件类,它将Cache-Control标头设置为must-revalidate, no-cache以进行开发,但这似乎只影响不在我的/static目录中的URL。

10 个答案:

答案 0 :(得分:19)

@Erik Forsberg的回答对我有用。这就是我必须做的事情:

  • INSTALLED_APPS中注释settings.py中的staticfiles应用:

    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.messages',
        #'django.contrib.staticfiles',
    )
    
  • STATIC_URL变量设置为settings.py

    STATIC_URL = '/static/'
    
  • 在我的项目基地urls.py中添加一个条目:

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

请注意,我还在中间件类Cache-Control中设置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

然后将其包含在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',
    )

答案 1 :(得分:16)

Django的contrib.staticfiles应用程序会通过覆盖runserver命令自动为您提供静态文件。使用此配置,您无法控制它为静态文件提供服务的方式。

您可以通过向runserver命令添加--nostatic选项来阻止staticfiles应用程序提供静态文件:

./manage.py runserver --nostatic

然后你可以编写一个url配置来手动提供带有标题的静态文件,这些标题会阻止浏览器缓存响应:

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)),
    )

如果您希望manage.py runserver命令默认启用--nostatic选项,则可以将其放在manage.py中:

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

答案 2 :(得分:9)

假设您正在使用django.views.static.serve,它看起来不像 - 但编写自己的视图只调用django.views.static.serve,添加Cache-Control标头应该相当容易。

答案 3 :(得分:9)

我非常简单的解决方案:

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)

答案 4 :(得分:2)

在较新版本的Django中,一个非常简单的解决方案是像这样修改项目网址:

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

# YOUR urlpatterns here... 

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, view=cache_control(no_cache=True, must_revalidate=True)(serve))

通过查看staticfiles如何自动修改url并仅添加视图装饰器来达到此目的。我真的不明白为什么这不是默认值,因为这仅用于开发。该视图能够正确处理“ If-Modified-Since” HTTP标头,因此始终发出请求,但仅在更改时传送内容(通过查看文件上的修改时间戳来判断)。

为此,您必须在使用--nostatic时添加runserver,否则上述更改将被忽略。

重要编辑:我以前没有用过,因为我没有使用--nostatic,并且never_cache装饰器还包含no-store,这意味着未更改文件总是被重新传输,而不是返回304 Not Modified

答案 5 :(得分:1)

对于较新的Django,中间件类的编写方式已发生了一些变化。

按照上面@aaronstacy的所有说明进行操作,但对于中间件类,请使用以下命令:

class NoCache(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        response['Cache-Control'] = 'must-revalidate, no-cache'
        return response

答案 6 :(得分:1)

使用whitenoise。运行服务器中提供的静态文件存在很多问题,并且这些问题已在whitenoise中修复。它也更快。他们已经talked about just replacing the built-in static serving with it,但是还没有人解决。

在开发中使用它的步骤...

安装pip install whitenoise

将以下内容添加到settings.py的末尾:

if DEBUG:
    MIDDLEWARE = (
        'whitenoise.middleware.WhiteNoiseMiddleware',
    ) + MIDDLEWARE
    INSTALLED_APPS = (
        'whitenoise.runserver_nostatic',
    ) + INSTALLED_APPS

答案 7 :(得分:0)

这与Django没有任何关系,因为在使用pip重新安装Django之后没有任何改变。

这是浏览器的行为,因此您只需要清除浏览器的缓存图像文件。

参考

Chrome Clear cache and cookies

答案 8 :(得分:0)

这很简单,如果您使用的是Django 2.0 +

步骤1:在settings.py(项目级别)中将“ django.contrib.staticfiles”作为注释

INSTALLED_APPS = [

# 'django.contrib.staticfiles',

]

第2步:将以下内容导入urls.py(项目级别)

     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

第3步:在urlpatterns之后的urls.py(项目级别)中添加以下行

urlpatterns = [

]

if settings.DEBUG:

    urlpatterns += static(settings.STATIC_URL, view=never_cache(serve))

确保在您的settings.py中声明了STATIC_URL

STATIC_URL = '/static/'

答案 9 :(得分:0)

staticfiles 应用程序通过 overriding the runserver command 实现静态文件的服务。我们可以做同样的事情:再次覆盖这个命令并实现一个关闭缓存的自定义处理程序。

请注意,您的 django 应用程序必须位于 django.contrib.staticfiles 中的 INSTALLED_APPS 之前,否则您的命令将被忽略。

# your_django_app/management/commands/runserver.py

from django.utils.cache import add_never_cache_headers
from django.contrib.staticfiles.handlers import (
    StaticFilesHandler as BaseStaticFilesHandler,
)
from django.contrib.staticfiles.management.commands.runserver import (
    Command as RunserverCommand,
)


class StaticFilesHandler(BaseStaticFilesHandler):
    def serve(self, request):
        response = super().serve(request)
        add_never_cache_headers(response)
        return response


class Command(RunserverCommand):
    def get_handler(self, *args, **options):
        handler = super().get_handler(*args, **options)

        # Check that serving static files is enabled
        if isinstance(handler, BaseStaticFilesHandler):
            # If yes, replace the original handler with our custom handler
            handler = StaticFilesHandler(handler.application)

        return handler