如何在Heroku上设置Django-Compressor,将离线压缩到S3

14

我遵循了在Stack Overflow和不同博客中发现的所有QA建议,一切在我的开发机器上都正常工作,但在Heroku上什么都不起作用。

以下是我的设置:

DEFAULT_FILE_STORAGE = 'arena.utils.MediaRootS3BotoStorage' # media files
# storage

AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_PRELOAD_METADATA = True # necessary to fix manage.py collectstatic command to only upload changed files instead of all files

S3_URL = 'https://%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = S3_URL + '/media/'

STATIC_URL = S3_URL + '/static/'

ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/'


COMPRESS_URL = STATIC_URL
COMPRESS_OFFLINE = True
COMPRESS_STORAGE = 'utils.CachedS3BotoStorage'
STATICFILES_STORAGE = COMPRESS_STORAGE
当我运行collectstatic/compress时,一切都很好,我可以看到文件被收集到S3并放置在正确的位置。我能看到清单文件。 使用compressor标签加载任何页面时,会显示错误OfflineGenerationError: You have offline compression enabled but key "d2a53169c44dec41ce3ee7da19b2b9d4" is missing from offline manifest.再次运行python manage.py compress没有解决问题。当我检查清单文件时,确实找不到它所寻找的密钥。 这里出了什么问题? 我已经检查过的问题: 如何配置django-compressor和django-staticfiles与亚马逊的S3? Django Compressor with S3 URL Heroku 配置具有远程存储(django-storage - amazon s3)的django压缩机

我认为这与您如何向模板添加较少的文件有关。在开发过程中,我动态地添加它们是可以的。但当您使用manage.py compress命令时,它无法看到动态添加的文件,并且无法压缩它们。 - Jacob Valenta
@JacobValenta 我的模板中没有less文件。我在Pycharm上每次保存时都有一个自动工作的编译器。manage.py compress 在Heroku上可以工作,没有抛出任何错误,但是当我尝试加载页面时,每次都会得到相同的错误。就好像它无法读取清单或其他东西一样。 - Neara
3个回答

1

在我的电脑上,我有非常相似的配置,并且已经成功使用压缩器超过2年了。

settings.py

COMPRESS_STORAGE = 'MyAwesomeApp.app.CachedS3BotoStorage.CachedS3BotoStorage'

AWS_ACCESS_KEY_ID = '#######'
AWS_SECRET_ACCESS_KEY = '########################+#########+BqoQ'
AWS_STORAGE_BUCKET_NAME = 'myAmazonS3cdn.myawesomewebsite.com'
AWS_S3_SECURE_URLS = False
AWS_QUERYSTRING_AUTH = False

COMPRESS_ROOT = 'MyAwesomeApp/static'
STATIC_ROOT = 'MyAwesomeApp/static/javascript'
COMPRESS_OUTPUT_DIR = 'compressed'
STATICFILES_STORAGE = COMPRESS_STORAGE

STATIC_URL = "http://myAmazonS3cdn.myawesomewebsite.com/"
COMPRESS_URL = STATIC_URL
COMPRESS_ENABLED = True

CachedS3BotoStorage.py

from django.core.files.storage import get_storage_class
from storages.backends.s3boto import S3BotoStorage

from django.core.files.base import File

class CachedS3BotoStorage(S3BotoStorage):
    """
    S3 storage backend that saves the files locally, too.
    """
    def __init__(self, *args, **kwargs):
        super(CachedS3BotoStorage, self).__init__(*args, **kwargs)
        self.local_storage = get_storage_class("compressor.storage.CompressorFileStorage")()

    def save(self, name, content):
        name = super(CachedS3BotoStorage, self).save(name, content)
        self.local_storage._save(name, content)
        return name

我在本地运行 python manage.py compress 命令,并在我的静态文件目录上生成了清单。Heroku 只处理 collectstatic 并将最新的清单版本提供给我的 CDN。

祝好,


我遇到了一个问题,加上 AWS_QUERYSTRING_AUTH = False 终于让它工作了。否则签名会随时间变化而改变。 - KVISH
这个问题并没有得到很好的记录,但在使用AWS_QUERYSTRING_AUTH参数之前,我一直卡在“请求已过期”的错误上。 - André Teixeira
是的,我之前做的是 AWS_QUERYSTRING_EXPIRE = 63115200。这将请求过期时间设置为从现在开始的2年。但即使如此,这也不是最好的解决方案。 - KVISH

1
我用一些代码完成了上述解决方案,以修复在Amazon S3中创建多个manifest_%.json文件的问题。
在setting.py中:
STATICFILES_STORAGE = 'your_package.s3utils.CachedS3BotoStorage'

在s3utils.py中:
from storages.backends.s3boto import S3BotoStorage
from django.core.files.storage import get_storage_class

class CachedS3BotoStorage(S3BotoStorage):
    """
    S3 storage backend that saves the files locally, too.
    """
    location = 'static'

    def __init__(self, *args, **kwargs):
        super(CachedS3BotoStorage, self).__init__(*args, **kwargs)
        self.local_storage = get_storage_class(
            "compressor.storage.CompressorFileStorage")()

    def url(self, name):
        """
        Fix problem images admin Django S3 images
        """
        url = super(CachedS3BotoStorage, self).url(name)
        if name.endswith('/') and not url.endswith('/'):
            url += '/'
        return url

    def save(self, name, content):
        name = super(CachedS3BotoStorage, self).save(name, content)
        self.local_storage._save(name, content)
        return name

    # HERE is secret to dont generating multiple manifest.json and to delete manifest.json in Amazon S3
    def get_available_name(self, name):
        if self.exists(name):
            self.delete(name)
        return name

0
我找到了一个包含 post_compile 钩子的 Git 存储库来解决这个问题。它在 Heroku 构建 Django 应用后运行压缩,并在压缩设置中安装 lessc(如果需要)。

https://github.com/nigma/heroku-django-cookbook


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接