11

我将 django-storages 用于 S3(和 S3BotoStorage)的静态文件。当我从本地机器收集静态时,行为与预期一致,仅将修改后的文件推送到 S3。这个过程需要 python-dateutils 1.5 来检查修改时间。

但是,在 Heroku 上执行相同操作会导致每个文件都被推送,尽管设置是相同的。然后我查看了 Heroku 本身文件的修改时间,看起来 os.stat(static_filename).st_mtime 与上次推送的时间相同。

这是预期的行为吗?即使 git 没有变化,heroku 是否会复制文件?

4

6 回答 6

15

尝试设置DISABLE_COLLECTSTATIC=1为您的应用程序的环境设置 - 这应该禁止它在每次推送时运行。

有关详细信息,请参阅本文 - https://devcenter.heroku.com/articles/django-assets

> Sometimes, you may not want Heroku to run collectstatic on your behalf.
> You can disable collectstatic by enabling user-env-compile as well:

$ heroku labs:enable user-env-compile
$ heroku config:set DISABLE_COLLECTSTATIC=1

我发现简单地设置配置就可以了——不需要也启用user-env-compile——可能是这已经从实验室转移到生产中了?

注意部署由 Heroku python buildpack 管理,您可以在此处查看 - https://github.com/heroku/heroku-buildpack-python/

编辑 1

我刚刚对此进行了一系列测试,并且可以确认DISABLE_COLLECTSTATIC确实禁用了 collectstatic,无论user-env-compile设置如何 - 我认为现在在主干线中(但这是猜测)。似乎并不关心设置是什么 - 如果DISABLE_COLLECTSTATIC作为配置变量存在,则使用它。

于 2014-02-25T16:57:40.717 回答
8

我强烈建议将collectfast 包用于任何到 s3 的 django 静态部署,无论是本地的还是来自您的 heroku 服务器。它忽略修改日期并利用 md5 哈希,s3 api 将非常快速地提供这些哈希,以及(可选)缓存以使您的静态部署缩放。我的静态部署从大约 10-15 分钟到不到 2 分钟,并且只部署了实际更改的文件。

于 2014-01-03T17:25:34.510 回答
5

我刚刚遇到了同样的问题,并联系了 Heroku 的支持人员以了解发生了什么。我对他们的问题是

我在进行一些部署时遇到了一个时髦的问题。似乎在每次推送时,所有文件的修改日期都会更新为新的部署/git推送发生的时间。这是预期的行为吗?

考虑到 Django 的collectstatic命令仅在评估文件是否应复制到静态资产的最终存储后端时检查文件的修改日期,这意味着在每次新推送时,首先从远程存储中删除所有文件(在此案例S3),然后重新上传。就带宽消耗和请求而言,这是一个非常缓慢和浪费的过程。

我今天从 Heroku 的支持人员之一“Caio”那里得到的答案是

嗨,这就是它目前的工作方式,是的。我正在将您的反馈发送给我们的运行时团队,看看我们是否可以使用原始日期打包文件。

于 2013-01-22T16:49:28.993 回答
1

为什么不从本地机器运行 collectstatic?

python manage.py collectstatic --noinput --settings=settings.[prod]
于 2013-09-11T14:37:47.257 回答
1

正如 Alen 所证实的,Heroku 在部署时会更改文件的修改日期。但是,Amazon S3 还有一个名为 etag 的属性,它是文件内容的 md5 哈希。可以使用它来检查文件是否已更改而不是修改日期,如在此 Django 片段中实现的那样。

我拿了那个代码,打包它并修复了我发现的一些错误,并将它作为django-s3-collectstatic放在 Github 上。它包括一个fasts3collectstatic只上传新文件的新管理命令。检查 Github 页面以获取安装说明。

于 2013-03-19T12:45:54.420 回答
0

我同意这很烦人——你可以做几件事。我覆盖了 collectstatic 命令并将其连接到我的生产设置中。以下是我使用的命令:

```

from django.core.management.base import BaseCommand
class Command(BaseCommand):
    args = '< none >'
    help = "disables collectstatic cmd in contrib"
    def handle(self, *args, **kwargs):
        print 'collectstatic disabled'

```

我把它保存在 mysite/disablecollectstatic/management/commands 然后在生产设置中:

INSTALLED_APPS += ('mysite.disablecollectstatic',)

或者,您可以使用 Heroku 在实际调用命令之前先进行空运行的事实。如果它失败了,它将不会运行它,这意味着您可能会制造错误(例如,通过删除设置中的静态根目录),但这种方法让我感到紧张:

https://devcenter.heroku.com/articles/django-assets#detection

于 2013-01-23T20:12:38.560 回答