Django:如何在开发环境中获取静态文件的文件路径?
首先介绍一些背景。我使用以下“技巧”来防止浏览器对静态文件(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果使用 django.contrib.staticfiles,这里是 findstatic 命令(django/contrib/staticfiles/management/commands/findstatic.py)应该有帮助。它使用 finders.find 来定位文件。
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.