Django:如何在开发环境中获取静态文件的文件路径?

发布于 2025-01-07 13:07:01 字数 1380 浏览 0 评论 0原文

首先介绍一些背景。我使用以下“技巧”来防止浏览器对静态文件(CSS、JS 等)进行不需要的缓存:

<script src="{{ STATIC_URL }}js/utils.js?version=1302983029"></script>

当版本字符串在后续页面加载时发生更改时,它会使浏览器从服务器重新获取静态文件。 (谷歌“css 缓存”了解有关此技巧的文章。)

我希望浏览器获取静态文件的最新版本,但我也希望在文件未更改时允许浏览器缓存。换句话说,我希望当且仅当静态文件已更新时版本字符串才会更改。我还想自动生成版本字符串。

为此,我使用静态文件的上次修改时间作为版本字符串。我正在制作一个自定义模板标记来执行此操作:

<script src="{% versioned_static 'js/utils.js' %}"></script>

以下是模板标记的工作原理:

import os.path
from django import template
from django.conf import settings

class VersionedStaticNode(template.Node):
    ...
    def render(self, context):
        # With the example above, self.path_string is "js/utils.js"
        static_file_path = os.path.join(settings.STATIC_ROOT, self.path_string)
        return '%s?version=%s' % (
            os.path.join(settings.STATIC_URL, self.path_string),
            int(os.path.getmtime(static_file_path))
            )

要获取静态文件的上次修改时间,我需要知道其在系统上的文件路径。我通过加入 settings.STATIC_ROOT 和来自该静态根的文件的相对路径来获取此文件路径。这对于生产服务器来说非常好,因为所有静态文件都收集在 STATIC_ROOT 中。

然而,在开发服务器上(使用manage.py runserver命令),静态文件不会在STATIC_ROOT处收集。那么在开发中运行时如何获取静态文件的文件路径呢?

(澄清我的目的:我想要避免的缓存情况是浏览器使用新的 HTML 和旧的 CSS/JS 不匹配。在生产中,这可能会极大地迷惑用户;在开发中,这可能会让我和其他开发人员感到困惑,并迫使我们经常刷新页面/清除浏览器缓存。)

Some background first. I'm employing the following "trick" to prevent undesired browser caching of static files (CSS, JS, etc.):

<script src="{{ STATIC_URL }}js/utils.js?version=1302983029"></script>

When the version string changes on a subsequent page load, it makes the browser re-fetch the static file from the server. (Google "css caching" for articles on this trick.)

I want the browser to get the latest version of a static file, but I also want to allow browser caching when the file hasn't changed. In other words, I want the version string to change if and only if the static file has been updated. I also would like to generate the version string automatically.

To do this, I'm using the last-modified time of the static file as the version string. I'm making a custom template tag to do this:

<script src="{% versioned_static 'js/utils.js' %}"></script>

And here's how the template tag works:

import os.path
from django import template
from django.conf import settings

class VersionedStaticNode(template.Node):
    ...
    def render(self, context):
        # With the example above, self.path_string is "js/utils.js"
        static_file_path = os.path.join(settings.STATIC_ROOT, self.path_string)
        return '%s?version=%s' % (
            os.path.join(settings.STATIC_URL, self.path_string),
            int(os.path.getmtime(static_file_path))
            )

To get the static file's last-modified time, I need to know its filepath on the system. I get this filepath by joining settings.STATIC_ROOT and the file's relative path from that static root. This is all well and good for the production server, since all static files are collected at STATIC_ROOT.

However, on a development server (where the manage.py runserver command is being used), static files aren't collected at STATIC_ROOT. So how do I get the filepath of a static file when running in development?

(To clarify my purpose: the caching situation I want to avoid is the browser using a mismatch of new HTML and old CSS/JS. In production, this can greatly confuse users; in development, this can confuse me and other developers, and forces us to refresh pages/clear the browser cache frequently.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半枫 2025-01-14 13:07:01

如果使用 django.contrib.staticfiles,这里是 findstatic 命令(django/contrib/staticfiles/management/commands/findstatic.py)应该有帮助。它使用 finders.find 来定位文件。

    from django.contrib.staticfiles import finders

    result = finders.find(path, all=options['all'])

    path = smart_unicode(path)
    if result:
        if not isinstance(result, (list, tuple)):
            result = [result]
        output = u'\n  '.join(
            (smart_unicode(os.path.realpath(path)) for path in result))
        self.stdout.write(
            smart_str(u"Found '%s' here:\n  %s\n" % (path, output)))

If using django.contrib.staticfiles, here's an extract of the findstatic command (django/contrib/staticfiles/management/commands/findstatic.py) that should help. It uses the finders.find to locate the file.

    from django.contrib.staticfiles import finders

    result = finders.find(path, all=options['all'])

    path = smart_unicode(path)
    if result:
        if not isinstance(result, (list, tuple)):
            result = [result]
        output = u'\n  '.join(
            (smart_unicode(os.path.realpath(path)) for path in result))
        self.stdout.write(
            smart_str(u"Found '%s' here:\n  %s\n" % (path, output)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文