Сборщик Django из Heroku каждый раз подталкивает S3

Я использую django-хранилища для статических файлов с S3 (и S3BotoStorage). Когда я собираю статические данные с моей локальной машины, поведение выполняется так, как ожидалось, где только модифицированные файлы переносятся на S3. Для этого процесса требуется python-dateutils 1.5 для проверки на время изменения.

Однако, делая то же самое на Heroku, каждый файл выталкивается независимо, хотя настройка такая же. Затем я просмотрел измененное время файлов самого Heroku, и похоже, что os.stat(static_filename).st_mtime совпадает с временем последнего нажатия.

Является ли это ожидаемым поведением? Геройку копирует файлы, даже если нет изменений от git?

Ответ 1

Попробуйте установить 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 - может быть, что это прошло из лабораторий в производство?

NB развертывание управляется сборником Heroku python buildpack, который вы можете увидеть здесь - https://github.com/heroku/heroku-buildpack-python/

РЕДАКТИРОВАТЬ 1

Я только что сделал кучу тестов на этом и могу подтвердить, что DISABLE_COLLECTSTATIC действительно отключает collectstatic, независимо от установки user-env-compile - я думаю, что теперь в основном туловище (но это предположение). Кажется, не волнует, что такое настройка - если DISABLE_COLLECTSTATIC существует как config var, он используется.

Ответ 2

Я настоятельно рекомендую использовать collectfast package для любого статического развертывания django для s3, будь то локального или с вашего сервера heroku. Он игнорирует измененные даты и использует хеши md5, которые s3 api будет обеспечивать очень быстро и (необязательно) кеширование, чтобы увеличить статическое развертывание. Потребовалось мое статическое развертывание от ~ 10-15 минут до < 2 минуты и только разворачивает файлы, которые действительно изменились.

Ответ 3

У меня была такая же проблема, и я связался с поддержкой Heroku, чтобы узнать, что происходит. Мой вопрос к ним был

Я столкнулся с проблемой фанки, занимающейся некоторыми развертываниями. Похоже, что при каждом нажатии дата, измененная на все файлы, обновляется до того момента, когда произойдет новое развертывание / git. Это предполагаемое поведение?

При рассмотрении того, что команда Django collectstatic проверяет только измененную дату в файлах при оценке того, должен ли файл копироваться в конечный файл хранилища для статических активов, это означает, что при каждом новом нажатии все файлы сначала удаляются из удаленное хранилище (в данном случае S3), а затем повторно загруженное. Это очень медленный и расточительный процесс с точки зрения потребляемой полосы пропускания и запросов.

Ответ, который я получил сегодня от "Caio", одного из сотрудников поддержки Heroku, был

Привет, как он работает в данный момент, да. Я направляю ваши отзывы в нашу команду во время выполнения, чтобы узнать, можем ли мы упаковать файлы с их исходными датами.

Ответ 4

Как подтверждено Alen, Heroku изменяет измененную дату файлов при ее развертывании. Тем не менее, Amazon S3 также имеет атрибут etag, который является хешем md5 содержимого файла. Можно использовать это, чтобы проверить, изменились ли файлы вместо измененной даты, как реализовано в этом фрагменте Django.

Я взял этот код, упаковал его и исправил некоторые ошибки, которые я нашел, и поместил их в Github как django-s3-collectstatic. Он включает новую команду управления fasts3collectstatic, которая только загружает новые файлы. Для получения инструкций по установке проверьте страницу Github.

Ответ 5

Почему бы не запустить сборку с локальной машины?

python manage.py collectstatic --noinput --settings=settings.[prod]

Ответ 6

Я согласен, что это раздражает - есть пара вещей, которые вы можете сделать. Я переопределяю команду 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