【问题标题】:How do I reset the django cache for static file names?如何为静态文件名重置 django 缓存?
【发布时间】:2012-12-23 03:47:20
【问题描述】:

我对 Heroku 上托管的 django 1.4 站点有疑问。我们将 Memcache 用于各种缓存,例如模板和静态资产缓存。 [更新:根据 django 文档,django 似乎没有将 memcache 用于模板加载器缓存]

有时当我将网站推送到 heroku 时,静态 css 文件的链接在缓存清除之前不会更新(手动或我猜测它何时超时,因为它似乎会在几分钟后自行修复,如果我不管它)。

所以这是不可接受的,因为我的 HTML 是新版本,而我的 css 将是旧版本,直到缓存更新并且 url 更改为新的 css 文件。

例子:

该站点具有 html(我们将其称为 v1)并链接到一个 css 文件,例如: application.5e6e7ad87005.css

我对 application.css 文件进行更改并推送站点。这会导致 staticfiles 的东西生成一个新的 css 文件名,让我们说: application.5e6e7ad87006.css

问题是在我的html页面上,它们仍然都链接到旧文件(application.5e6e7ad87005.css)。

我想只清除缓存文件名的缓存(至少,我假设这是问题所在,如果有人认为这是一个不同的问题,请告诉我)以免丢失我的其他缓存(模板缓存、查询缓存等)

从搜索来看,我似乎只能一次清除所有缓存,而不是单个缓存。

【问题讨论】:

    标签: django caching heroku django-staticfiles


    【解决方案1】:

    这完全取决于您对模板使用的缓存策略。您是否缓存了每个模板和呈现的页面的全部内容?

    如果是这样,那么我建议改用template-fragment caching。这个想法是你只会缓存每个模板的某些渲染成本很高的部分。您不会缓存那些渲染速度应该很快的部分,例如指向您的 css 文件的链接。

    我建议您也研究一下django-compressor,它在动态缩小 CSS/JS 文件和确保系统地使用这些文件的最新版本(前提是您没有缓存当然是指向这些文件的链接)。

    【讨论】:

    • 我启用了默认模板缓存,但我们没有明确缓存任何内容:( ('django.template.loaders.cached.Loader', ( 'hamlpy.template.loaders.HamlPyFilesystemLoader', 'hamlpy.template.loaders.HamlPyAppDirectoriesLoader', 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ),), )
    • 我想这意味着无论默认设置是什么,我们的整个模板都会被缓存(我认为我们将超时设置为“500”,这就是 heroku 插件所说的设置它的方式.
    • 做模板片段缓存会是 'django.template.loaders.cached.Loader' 模板加载器的更好替代方案,还是不相关?
    • 将其标记为最佳答案,因为模板缓存似乎是问题所在 - 我会在推送时考虑清除它,但我希望 django 在我的静态文件更改时自动执行此操作.
    • 使用 'django.template.loaders.cached.Loader' 是一个不错的性能改进,但是正如您所见,刷新内容可能有点棘手。不过要注意的一件事是,这些模板缓存在缓存引擎(即在您的情况下为 Memcached)中,而是缓存在 Django 进程的内存中。这意味着要刷新您的模板,您实际上需要重新加载内存中的 Python 代码,方法是重新启动您的 Web 服务器(例如,如果您使用的是 Apache),或者简单地执行 'touch '。
    【解决方案2】:

    在这种情况下,我会说heroku config:add ... 是你的朋友。

    例如:您可以创建一个 bash 脚本,为您推送最新的应用程序,然后触发,例如:heroku config:add GIT_LAST_COMMIT=$(git rev-parse HEAD)

    然后在您的 Python 代码中,您可以使用 os.environ['GIT_LAST_COMMIT'] 引用该变量。

    例如,这是我的 Heroku 应用:http://stormy-badlands-7331.herokuapp.com/

    app.py 的代码是:

    import os
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
      return 'Hello World! The latest commit sha is %s' % os.environ['GIT_LAST_COMMIT']
    
    if __name__ == '__main__':
      # Bind to PORT if defined, otherwise default to 5000.
      port = int(os.environ.get('PORT', 5000))
      app.run(host='0.0.0.0', port=port)
    

    而我的deploy.sh 是:

    git push heroku master
    heroku config:add GIT_LAST_COMMIT=$(git rev-parse HEAD)
    

    请注意,我在推送后会更新变量,这样可以确保用户不会在新哈希下获得旧资产。

    然后,您可以将此os.environ['GIT_LAST_COMMIT'] 用作x var,例如,在加载您的资产时,例如:

    <link rel="stylesheet" type="text/css" href="/assets/css/styles.css?{{ git_last_commit}}" />
    

    【讨论】:

    • 嗯,我不喜欢这种方法有几个原因: 1) 使用查询字符串对某些代理服务器效果不佳,最好使用实际文件名。 2)这将在我每次推送时修改每个文件,而不仅仅是更改的文件。每当文件更改时,Django 的静态文件应用程序在生成新文件名方面已经做得非常好。我遇到的问题只是更新了我推送时链接到文件的 html - 似乎我的模板缓存太激进了。
    最近更新 更多