Django不会刷新静态文件

Posted

技术标签:

【中文标题】Django不会刷新静态文件【英文标题】:Django won't refresh staticfiles 【发布时间】:2015-03-10 18:07:45 【问题描述】:

我在 django 模板上引用了一个 javascript 文件:

 <script src="% static 'js/login.js' % "></script>

我对该 js 文件进行了一些更改。然后,我刷新页面,我看不到更改发生。

如果我从文件中删除 JavaScript 并将其放入 html 中,它可以正常工作,但如果我尝试使用外部 js 文件执行此操作,则它不会。我已经尝试关闭服务器并运行 runserver 几次,我也尝试从 Firefox 更改为 Chrome。这根本没有意义。请帮助我理解,我可以将所有 js 包含在 HTML 中,但让我感到困扰的是,我不能再以正常的方式做到这一点了。

有关此错误的更多详细信息(我发现的 #$&%# 最奇怪的事情):

JavaScript 是这样的:

old_sentence = "Dig that hole, forget the sun"  // this is what I want to change
$("#jqselector").text(old_sentence)

new_sentence = "Run, rabbit, run"  // this is the new sentence, it just won't show up.

所以,我换了js,重启了服务器,html还是显示老句。然后我删除了对login.js文件的引用,把所有的js里面的script标签放到了HTML中,当然新的句子出现了。然后我包含login.js文件,注释掉html里面的js但是我删除了login.js文件里面的所有内容,使它成为一个空文件……但是旧的句子仍然出现。

因此,旧的login.js 文件必须在我不知道的某个地方兑现。然后我打开 Chrome 并再次尝试,同样的问题。

可能是什么?是否有强制 django 刷新静态文件的选项?我认为重新启动服务器就足够了。我应该重新启动计算机吗?

【问题讨论】:

你试过运行python manage.py collectstatic吗?听起来您正在修改 javascript 的工作副本,并且它正在引用收集/过期的文件。 您是否尝试使用 Ctrl-F5 刷新页面并清除缓存? 感谢您的 cmets 和您的时间。我已经发现了错误,这确实是一个奇怪的错误。我发现 django 将本地环境静态文件指向我在部署时使用的 AWS 存储桶。所以...运行 collectstatic 是我猜的解决方案的一部分,剩下的就是重新配置我的静态文件设置并以某种方式解决 AWS Bucket 问题。 如果你在 django 中使用 uwsgi,你可能需要重启 uwsgi 以避免提供旧内容***.com/a/12632061/4061047 我不确定这是否仍然相关,但如果您设置了 staticfiles_dirs 并且不仅是静态根目录,那么 django 可能会在开发环境中提供来自 _dirs 的静态文件,而不是来自根。这就是发生在我身上的事情。如果我在根目录中处理静态文件,则在运行 collectstatic 之前不会应用任何更改。如果我在 _dir 中处理静态文件,则 Ctrl+F5 会应用更改。 【参考方案1】:

清除静态文件python manage.py collectstatic --noinput --clear。这将事先清除静态。

清除浏览器缓存

在每次加载时在 js 文件包含后添加一个随机字符串,例如 jquery.js?rand=23423423

【讨论】:

第一个选项不适用于开发环境。最后一点是一个很好的提示,直到现在我一直在更改实际的文件名,但这要好得多:) 如何将随机参数添加到 为什么要清除所有静态文件?这是否意味着您必须重新上传它们? 这毁了我的服务器!它删除了我的整个 git 存储库。为什么这是选定的答案? 我尝试了你的第一种方法,它删除了我所有的静态文件-.-【参考方案2】:

对于窗口用户, ctrl+f5 在开发服务器上完成这项工作,如果这不起作用,则使用命令 python manage.py collectstatic 正在工作,否则某些答案中提到的其他方式确实有风险,所以最好备份您的静态文件。

【讨论】:

【参考方案3】:

我今晚正在追逐一个 css 静态文件更改。通过 Django 教程。 我的 Django html 页面不会在我的 base.css 文件中显示更新后的 css。

我会看到原始的 base.css,但没有我对文件的更新。这是在开发环境中。

我不认为 django 仅在生产中运行 coll ecstatic 后才在 dev 上缓存静态。

为了快速解决问题,我更改了测试站点的名称。 base.css 文件到 base1.css 和 html 页面链接到 base1.css

重新加载的页面和我更新的 CSS 生效。没有最好的解决方案。但快速修复。

【讨论】:

【参考方案4】:

静态文件的更改不起作用”。这可能有多种原因。

    您的浏览器是storing cache 的静态文件。

    解决方案(一):打开Incognito/Private window

    解决方案(2):使用硬刷新:

    对于 mac:cmd + shift + r 对于其他人:ctr + shift + r

    如果您在生产中遇到此问题,请按照以下步骤操作:

    通过以下命令删除 staticfiles 文件夹: sudo rm -rf staticfiles [在你的项目目录中]

    现在运行collectstatic 命令:python3 manage.py collectstatic

    重启gunicorn,通过以下命令:sudo systemctl restart gunicorn

    重启nginx,通过以下命令:sudo systemctl restart nginx

有时浏览器会将这些静态文件数据(作为缓存)存储一段时间。几个小时后问题可能会消失。

希望这能解决您的问题。

【讨论】:

不知道硬刷新功能。非常感谢。 第一点足以解决我的问题。谢谢。【参考方案5】:

只需运行python manage.py collectstatic 就可以解决问题。然后使用ctrl + F5 硬刷新浏览器,这应该适用于所有浏览器。

【讨论】:

【参考方案6】:

简单的摆脱方法,硬刷新cmd+shift+r/ctr+shift+r

硬刷新是一种清除特定页面的浏览器缓存的方法,以强制它加载页面的最新版本。 在浏览器上cmd+shift+r/ctr+shift+r

【讨论】:

请在您的答案中添加一些解释,以便其他人可以从中学习 - 是什么让您认为这比其他获得数十人支持的方法更有效? 而不是停止服务器并做一些额外的事情。即运行命令或向项目添加一些代码。只需通过 cmd+shift+r 刷新页面即可。 (硬刷新)硬刷新是一种清除特定页面的浏览器缓存的方法,强制它加载页面的最新版本。 请通过编辑将所有信息添加到您的答案中【参考方案7】:

在重新收集静态文件后对我来说,Just Changes 反映在我身上。

$ python manage.py collectstatic --noinput --clear

现在运行你的服务器,希望它能正常工作。

$ python manage.py runserver

【讨论】:

【参考方案8】:

您需要破坏浏览器缓存。当DEBUG=True 时,此模板标签将输出基于时间的 uuid。否则它将寻找PROJECT_VERSION 环境变量。如果没有找到,它将输出一个静态版本号。

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

register = template.Library()                                                                                                            

@register.simple_tag(name='cache_bust')                                                                                                  
def cache_bust():                                                                                                                        

    if settings.DEBUG:                                                                                                                   
        version = uuid.uuid1()                                                                                                           
    else:                                                                                                                                
        version = os.environ.get('PROJECT_VERSION')                                                                                       
        if version is None:                                                                                                              
            version = '1'                                                                                                                

    return '__v__=version'.format(version=version)

你会在这样的模板中使用:

% load cache_bust %

<link rel="stylesheet" href="% static "css/project.css" %?% cache_bust %"/>

这是结果输出:

<link rel="stylesheet" href="/static/css/project.css?__v__=7d88de4e-7258-11e7-95a7-0242ac130005"/>

【讨论】:

这看起来是个不错的解决方案!但是究竟应该在哪里添加这段代码呢? @LuizTauffer 看看这个:docs.djangoproject.com/en/3.2/howto/custom-template-tags app 目录中应该有一个名为 templatetags 的文件夹,里面有这个文件(任何你想要的名字)和一个 init.py。然后使用 % file_name % 将其加载到模板中【参考方案9】:

一种解决方案是将设置更改为以下内容:

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

这样做是创建静态文件的副本,文件名中包含内容哈希(运行collectstatic 时)。这样,当内容更改时,文件名也会更改,并且不会使用旧缓存。唯一的问题是它在 DEBUG = True 模式下无法使用,因此您必须执行 shift-reload 才能进行硬重载。

您可以阅读docs on ManifestStaticFilesStorage 了解更多信息。

编辑:我找到了 solution for making sure static files are not cached in dev 并将其发布在另一个问题上。

【讨论】:

【参考方案10】:

如果您不想在每次更改 CSS 和 JavaScript 文件时或在设置图像样式时刷新浏览器缓存,则需要使用可变路径组件动态设置 STATIC_URL。使用动态变化的 URL,每当更新代码时,访问者的浏览器将强制加载全新的未缓存静态文件。在这个秘籍中,我们将使用 os 中的上次编辑时间为 STATIC_URL 设置动态路径。

import os
from datetime import datetime    

def get_file_changeset(absolute_path):
    timestamp = max(map(lambda x: os.path.getmtime(x[0]), os.walk(os.path.join(absolute_path, 'static'))))
    try:
        timestamp = datetime.utcfromtimestamp(int(timestamp))
    except ValueError:
        return ""
    changeset = timestamp.strftime('%Y%m%d%H%M%S')
    return changeset

您的SETTINGS 的下一个更改:

from utils.misc import get_file_changeset
STATIC_URL = "/static/%s/" % get_file_changeset(BASE_DIR)

工作原理:get_file_changeset()函数将absolute_path 目录作为参数,并调用os.path.getmtime() 到每个嵌套目录中的每个文件,并找到最后编辑的文件(及其最大编辑时间)。时间戳被解析;转换为由年、月、日、时、分、秒组成的字符串;回来;并包含在 STATIC_URL 的定义中。注意:这样,您每次编辑静态文件时都必须重新加载开发服务器。

【讨论】:

【参考方案11】:

您可以在模板中的包含中添加额外的参数,而不是使用复杂的解决方案。

对于静态包括:

<script src="% static 'js/polls/polls.js' %?version=1"></script>

对于直接包括:

<link rel="stylesheet" type="text/css" href="/site_media/css/style.css?version=1" />  

注意代码中的?version=1。每次修改css/js文件时,在模板中修改这个版本,这样浏览器就会强制重新加载文件。

如果您出于某种未知原因想要完全避免缓存,您可以使用当前时间戳而不是版本:

<link rel="stylesheet" type="text/css" href="/site_media/css/style.css?% now "U" %" />

【讨论】:

这很奏效。我通常会全部重启:sudo systemctl daemon-reload &amp;&amp; sudo systemctl reload nginx &amp;&amp; sudo systemctl restart gunicorn。但是这次它在我的 CSS 上不起作用。将版本直接添加到样式表链接就可以了。谢谢。【参考方案12】:

您的浏览器将缓存图像和文件(包括 JavaScript)。首先,只清除缓存的图像和文件。然后在更改 .js 文件时在 chrome 中使用隐身模式或在 firefox 中使用隐私浏览,以便在页面刷新后立即看到它们

【讨论】:

【参考方案13】:

我也为这个问题苦苦挣扎了好几个小时。我曾尝试使用 Javascript 注入随机字符串,但这种方法看起来既愚蠢又丑陋。处理此问题的一种可能方法是引入自定义标签。详情请见document:

具体来说,您需要在您创建的任何应用程序中创建一个名为templatetags 的包(或者如果您愿意,也可以创建一个新应用程序)。然后你在这个包中创建任何文件,并编写如下内容:

from django import template
from django.utils.crypto import get_random_string
from django.templatetags import static

register = template.Library()


class StaticExtraNode(static.StaticNode):

    def render(self, context):
        return super().render(context) + '?v=' + get_random_string(32)


@register.tag('static_no_cache')
def do_static_extra(parser, token):
    return StaticExtraNode.handle_token(parser, token)


def static_extra(path):
    return StaticExtraNode.handle_simple(path)

那么您可以使用标签% static_no_cache '.../.../path...' % 来创建带有随机参数的路径!

我希望这会有所帮助!

【讨论】:

【参考方案14】:

如果没有其他方法,请在项目中搜索文件名并查找意外副本。如果您在某个时间点保存到了错误的位置(不同的应用),或者从旧应用中分离出新应用,则加载优先级可能会欺骗您。

【讨论】:

【参考方案15】:

听起来您的两个浏览器都缓存了 javascript 文件。在 Chrome 中,您可以通过按 Ctrl + Shift + Del 并勾选“缓存的图像和文件”来清除缓存。 Firefox 可能有类似的快捷方式。

您可以查看this question,了解在开发服务器上完全禁用静态文件缓存的技巧。

【讨论】:

没办法,作为一个优秀的程序员你不希望客户端以这种方式刷新:(【参考方案16】:

要刷新静态文件,您应该再次运行 python manage.py collectstatic

【讨论】:

他在使用runserver 的开发服务器上。静态文件直接从其原始位置加载,因此collectstatic 不会改变任何内容。

以上是关于Django不会刷新静态文件的主要内容,如果未能解决你的问题,请参考以下文章

django -静态文件能加载进入,但是在页面上却显示不出来

我在 django 中的静态文件不会被重新加载,除非我每次重新启动电脑时都重命名它们

Django 在使用开发服务器时不会提供静态文件

Django 不会在 VS Code 编辑器中解析静态文件的路径

Django学习——静态文件配置

Django_生产环境静态文件配置