Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html 使用Django进行静态文件版本控制_Html_Django_Nginx_Web Optimization - Fatal编程技术网

Html 使用Django进行静态文件版本控制

Html 使用Django进行静态文件版本控制,html,django,nginx,web-optimization,Html,Django,Nginx,Web Optimization,我正在为我的CSS/Javascript设置far future expires头,这样浏览器在缓存文件后就不会再请求文件了。我还有一个简单的版本控制机制,这样,如果文件发生更改,客户端就会知道 基本上我有一个模板标签,我做了一些类似 这将成为 模板标记打开一个文件javascript/c/c.js.v,在其中找到版本号并将其附加到查询字符串中。该版本由一个shell脚本生成(目前手动运行,可能会添加预提交钩子),该脚本检查文件是否已更改(使用git diff) 这一切正常,除了: 我也想为

我正在为我的CSS/Javascript设置far future expires头,这样浏览器在缓存文件后就不会再请求文件了。我还有一个简单的版本控制机制,这样,如果文件发生更改,客户端就会知道

基本上我有一个模板标签,我做了一些类似

这将成为

模板标记打开一个文件
javascript/c/c.js.v
,在其中找到版本号并将其附加到查询字符串中。该版本由一个shell脚本生成(目前手动运行,可能会添加预提交钩子),该脚本检查文件是否已更改(使用
git diff

这一切正常,除了:

我也想为图像实现同样的版本控制。但是图像可以从CSS中引用,CSS是一个静态文件(由nginx提供服务),因此没有模板标记

什么是更好的文件版本控制方法

或者,我正在考虑用中间件替换模板标记,该中间件在返回响应之前更改所有链接。这比模板标记要好,模板标记可能会被错误地忽略。但是仍然不能解决从CSS引用图像的问题

也知道,把这个版本作为查询字符串的一部分可能会给某些代理带来麻烦,而不是缓存文件——所以我考虑把文件名的版本部分——例如:代码> JavaScript /C/C.12345 .JS ./P>
注意:使用Django似乎无法解决这个问题(很明显,因为我甚至没有通过Django提供CSS)。但是必须有一个解决方案,可能涉及到一些nginx技巧。

我们使用这个简单的templatetag根据文件修改时间生成版本号:

import os
import posixpath
import stat
import urllib

from django import template
from django.conf import settings
from django.contrib.staticfiles import finders

register = template.Library()

@register.simple_tag
def staticfile(path):
    normalized_path = posixpath.normpath(urllib.unquote(path)).lstrip('/')
    absolute_path = finders.find(normalized_path)
    if not absolute_path and getattr(settings, 'STATIC_ROOT', None):
        absolute_path = os.path.join(settings.STATIC_ROOT, path)
    if absolute_path:
        return '%s%s?v=%s' % (settings.STATIC_URL, path, os.stat(absolute_path)[stat.ST_MTIME])
    return path
对于1.3版本之前的Django,该标签有更简单的版本:

@register.simple_tag
def staticfile(path):
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    url = '%s%s?v=%s' % (settings.MEDIA_URL, path, os.stat(file_path)[stat.ST_MTIME])
    return url
用法:

<link rel="stylesheet" href="{%  staticfile "css/style.css" %}" type="text/css" media="screen" />

将在我的预提交脚本中添加另一个步骤,用最小化CSS中版本文件的链接替换所有直接链接

看来没有更好的办法了。如果你有任何想法,请告诉我,我会考虑把这个标记为已接受的答案。
谢谢你的评论

这也可能有帮助:

我认为一个简单的解决方案可能是:

  • 将css文件编写为Django模板
  • 编写一个Django命令来呈现css模板(并将它们存储在可访问的地方)
  • 在部署脚本中调用此命令

  • 样式表资产

    对于样式表引用的资产,最好使用Sass和Compass。Compass有一个mixin,它将在样式表中引用的静态资产的末尾自动添加版本查询参数。版本号仅在重新生成样式表时更改(在本地开发时,使用
    compass-watch
    很简单)

    模板资产

    对于其他文件,我实际上会使用某种类型的post-pull钩子重写python模块,该模块的唯一目的是包含当前版本

    /var/www/aweso.me/
        ./files/
        ./private-files/
        ./static/
        ./project/
            ./manage.py
            ./fabfile.py
            ./.gitignore
            ./base/
                ./__init__.py
                ./wsgi.py
                ./settings/
                    ./__init__.py
                    ./modules
                        ./__init__.py
                        ./users.py
                        ./email.py
                        ./beta.py
                        ./redis.py
                        ./haystack.py
                    ./version.py
                    ./default.py
                    ./local.py
                    ./live.py
    
    您的后拉钩将创建:

    /var/www/aweso.me/project/base/settings/version.py
    
    其中将包含最新(或以前)的git提交哈希:

    __version__ = "0763j34bf"
    

    然后,在
    设置.live
    中使用简单的
    from.version导入
    ,您的模板标签就可以简单地使用
    from settings import ApplicationVersion
    将该查询参数写入缓存buster。

    下面的@paluh答案是您的最佳选择。从Django中的文件中提取文件MTIME不会比直接检查Django中文件的MTIME节省任何东西。这只会增加一层复杂性和另一个故障点(作为cron作业运行的shell脚本)。事实上,mtime可以使我的设置更简单-减少运行脚本的需要和对git的依赖。我通常不信任MTIME(在复制到另一个文件系统或备份时,MTIME可能会更改,或者…),但在这种情况下,我想这并不重要,因为源代码树总是在同一个位置。另外,如果mtime真的因为某种原因而改变,最糟糕的情况就是缓存失效。还不错。在部署前处理CSS文件怎么样?我也做了类似的事情,但没有用Django。这是一个定制的PHP,我首先想到了一个预提交步骤,在这个步骤中我处理文件,但这将不必要地污染我的git时间表。预部署并没有破坏我的git repo,但它还有另一个问题:您没有机会真正查看更改—如果出现问题,您发现可能太晚了。为了便于审查,我会选择预提交而不是预部署。由于图像不会经常更改,上述缺点并没有那么大。与我最初的解决方案有相同的问题。无法处理CSS中引用的图像(除非我通过Django提供CSS)。希望我能找到更好的方法。是的,如何最好地处理CSS文件中的图像是一个长期存在的问题。您不能利用
    MEDIA\u URL
    ,并且,与您的情况一样,您不能添加查询字符串或类似的内容来实现缓存。也就是说,除非您通过Django提供文件,但这是一个完全不同的can或WORM。然而,由于您的问题是使修改后的文件的缓存无效,因此可以推测,CSS引用的图像在修改时无论如何都会对应于CSS文件中的编辑。不一定总是这样,但在这里自我管理缓存失效应该不会太困难。