Django-compressor не устанавливает абсолютные пути изображения CSS на Heroku - программирование
Подтвердить что ты не робот

Django-compressor не устанавливает абсолютные пути изображения CSS на Heroku

Я использую django-compressor для конкатенации и сжатия моих CSS и JS файлов на этом сайте, Я обслуживаю статические файлы из ведра S3.

На моей локальной копии сайта, используя другой ведро S3, все это работает отлично. Но на реальном сайте, размещенном на Heroku, все работает, за исключением того, что относительные URL-адреса изображений в файлах CSS не переписываются.

например, эта строка в файле CSS:

background-image: url("../img/glyphicons-halflings-grey.png");

переписывается на:

background-image:url('https://my-dev-bucket-name.s3.amazonaws.com/static/img/glyphicons-halflings-grey.png')

на моем сайте разработки, но не затрагивается на сайте. Таким образом, веб-сайт заканчивается поиском pepysdiary.s3.amazonaws.com/static/CACHE/img/ для изображений (как относительно нового сжатого файла CSS).

На данный момент я поместил каталог в это место, содержащее изображения, но я не могу понять, почему существует эта разница. Оба сайта имеют это в своих настройках:

COMPRESS_CSS_FILTERS = [
    # Creates absolute urls from relative ones.
    'compressor.filters.css_default.CssAbsoluteFilter',
    # CSS minimizer.
    'compressor.filters.cssmin.CSSMinFilter'
]

И файлы CSS сводятся к минимуму просто отлично... но он, как и другой фильтр, не применяется на реальном сайте.

4b9b3361

Ответ 1

Недавно я столкнулся с этой проблемой на heroku, и запуск последней версии django-compressor (1.3) не решает проблему. Я предоставлю решение, которое я использую, а также объяснение проблем, с которыми я столкнулся на пути.

Решение

Я создал свой собственный "CssAbsoluteFilter", который удаляет настройки. DEBUG проверяет метод "Найти" следующим образом:

# compress_filters.py
from compressor.filters.css_default import CssAbsoluteFilter
from compressor.utils import staticfiles


class CustomCssAbsoluteFilter(CssAbsoluteFilter):
    def find(self, basename):
        # The line below is the original line.  I removed settings.DEBUG.
        # if settings.DEBUG and basename and staticfiles.finders:
        if basename and staticfiles.finders:
            return staticfiles.finders.find(basename)

# settings.py
COMPRESS_CSS_FILTERS = [
# 'compressor.filters.css_default.CssAbsoluteFilter',
'app.compress_filters.CustomCssAbsoluteFilter',
'compressor.filters.cssmin.CSSMinFilter',
]

Абсолютные URL теперь всегда работают для меня независимо от того, является ли DEBUG = True или False.

Проблема

Проблема связана с параметром "compressor.filters.css_default.CssAbsoluteFilter", вашим параметром DEBUG и тем фактом, что у heroku есть файловая система только для чтения и перезаписывает файлы приложений каждый раз при развертывании.

Причина, по которой сбой работает правильно на вашем сервере разработки, заключается в том, что CssAbsoluteFilter всегда будет находить ваши статические файлы, когда DEBUG = True, даже если вы никогда не запускаете "collectstatic". Он ищет их в STATICFILES_DIRS.

Когда DEBUG = False на вашем рабочем сервере, CssAbsoluteFilter предполагает, что статические файлы уже собраны в ваш COMPRESS_ROOT и не будут применять абсолютный фильтр, если он не может найти файлы.

Jerdez, автор django-compressor, объясняет это следующим образом:

CssAbsoluteFilter работает с DEBUG = False, если вы успешно предоставили файлы для работы. Во время разработки компрессоры используют статический поиск файлов как удобство, поэтому вам не нужно постоянно запускать коллекцию.

Теперь для героку. Несмотря на то, что вы сохраняете свои статические файлы на S3, вам также нужно хранить их на герою (с помощью CachedS3BotoStorage). Поскольку heroku является файловой системой только для чтения, единственный способ сделать это - позволить героку автоматически собирать ваши статические файлы во время развертывания (см. https://devcenter.heroku.com/articles/django-assets).

По моему опыту, запуск "heroku run python manage.py collectstatic --noinput" вручную или даже в вашем Procfile будет загружать файлы на S3, но он НЕ будет сохранять файлы в вашем каталоге STATIC_ROOT (какой компрессор использует по умолчанию как COMPRESS_ROOT). Вы можете подтвердить, что ваши статические файлы были собраны на герою, используя "heroku run ls path/to/gather".

Если ваши файлы были собраны на геройку успешно, вы также сможете сжать ваши файлы, без решения, которое я предоставил выше.

Однако, похоже, герой будет собирать только статические файлы, если вы внесли изменения в свои статические файлы с момента последнего развертывания. Если в ваши статические файлы не были внесены изменения, вы увидите что-то вроде "0 из 250 статических файлов, скопированных". Это проблема, потому что heroku полностью заменяет ваше содержимое приложения при развертывании, поэтому вы теряете все статические файлы, которые ранее были собраны в COMPRESS_ROOT/STATIC_ROOT. Если вы попытаетесь сжать ваши файлы после того, как собранные файлы больше не существуют на heroku, а DEBUG = False, CssAbsoluteFilter не заменит относительные URL-адреса с абсолютными URL-адресами.

Мое решение выше избегает проблемы герой в целом и заменяет относительные URL-адреса css абсолютными URL-адресами, даже когда DEBUG = False.

Надеемся, что другие люди также найдут эту информацию полезной.

Ответ 2

У меня была такая же проблема в течение месяца, но это исправлено в версии 1.3 (3/18/13, поэтому вы, вероятно, были на 1.2), поэтому просто обновите:

pip install -U django-compressor

Точная проблема, которую я отказался от разработки, но она связана с тем, что Heroku и CssAbsoluteFilter вызываются, но не работают при методе _converter. Рассматривая 1.3 журнал изменений, единственное связанное с ним совершение: https://github.com/jezdez/django_compressor/commit/8254f8d707f517ab154ad0d6d77dfc1ac292bf41

Я сдался, жизнь слишком короткая.

Ответ 3

Между тем это было зафиксировано в джанго-компрессоре 1.6. Из changelog:

Apply CssAbsoluteFilter to precompiled css even when compression is disabled

то есть. абсолютный фильтр запускается даже с DEBUG = True.