Невозможно подать статический носитель из S3 с Django

Мне нужно использовать Amazon S3 для подачи статических и мультимедийных файлов в мой проект Django.

Однако с этим я сталкиваюсь с множеством проблем. Во-первых, мой код:

s3utils.py

from storages.backends.s3boto import S3BotoStorage

class FixedS3BotoStorage(S3BotoStorage):
def url(self, name):
    url = super(FixedS3BotoStorage, self).url(name)
    if name.endswith('/') and not url.endswith('/'):
        url += '/'
    return url

StaticS3BotoStorage = lambda: FixedS3BotoStorage(location='static')
MediaS3BotoStorage = lambda: FixedS3BotoStorage(location='media')

В settings.py

DEFAULT_FILE_STORAGE = 'SpareGuru.s3utils.MediaS3BotoStorage'
STATICFILES_STORAGE = 'SpareGuru.s3utils.StaticS3BotoStorage'

AWS_HOST = "s3-ap-southeast-1.amazonaws.com"
AWS_ACCESS_KEY_ID = 'xx'
AWS_SECRET_ACCESS_KEY = 'yy'
AWS_STORAGE_BUCKET_NAME = 'zz'

S3_URL = 'http://%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
MEDIA_DIRECTORY = '/media/'
STATIC_DIRECTORY = '/static/'

STATIC_URL = "/static/"

MEDIA_URL = "/media/"

STATIC_ROOT = S3_URL + STATIC_DIRECTORY
COMPRESS_ROOT = STATIC_ROOT
MEDIA_ROOT = S3_URL + MEDIA_DIRECTORY

Вот проблемы, с которыми я сталкиваюсь:

  1. При беге ./manage.py collectstatic, он начинает загружать файлы на S3, и после пары файлов, я получаю Broken Pipe ошибка.

  2. При попытке запустить веб-страницу я получаю сообщение об ошибке: 'https://zz.s3.amazonaws.com/static/css/bootstrap.min.css?Signature=sign&Expires=1438359937&AWSAccessKeyId=xx' isn't accessible via COMPRESS_URL ('/static/') and can't be compressed,

Понятия не имею, что здесь происходит.

Изменить: Моя предыдущая политика разрешена только для чтения. Так что, возможно, это могло быть причиной того, что мой компрессор не смог создать файлы на S3. Я обновил политику, но все еще не работает. Обновленная политика:

{
"Statement": [
    {
        "Sid": "PublicReadForGetBucketObjects",
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": [
            "s3:GetObject"
        ],
        "Resource": [
            "arn:aws:s3:::zz/*"
        ]
    },
    {
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": [
            "arn:aws:s3:::zz",
            "arn:aws:s3:::zz/*"
        ],
        "Principal": {
            "AWS": [
                "my-arn:/goes=here"
            ]
        }
    }
]
}

И CORS Configuration для моего ведра это:

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

2 ответа

У меня это работает на моем собственном проекте Django. Я пошел и проверил различия. Вы можете попробовать добавить одну вещь:

AWS_QUERYSTRING_AUTH = False

на ваши settings.py. Это может помочь, по крайней мере, с вашей проблемой № 2.

Вот полный пример из моего settings.py. Примечание: я не использую S3 для статических файлов, только для мультимедиа.

from boto.s3.connection import SubdomainCallingFormat
AWS_CALLING_FORMAT = SubdomainCallingFormat()
DEFAULT_FILE_STORAGE = 'project.s3utils.MediaRootS3BotoStorage'
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', None)
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_KEY', None)
AWS_SECRET_KEY = os.getenv('AWS_SECRET_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
AWS_QUERYSTRING_AUTH = False
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '../',  'static')
MEDIA_ROOT = os.path.join(BASE_DIR, '../..',  'media')
MEDIA_URL = 'http://{!s}.s3.amazonaws.com/media/'.format(AWS_STORAGE_BUCKET_NAME)

Я верю твоему static а также media URL / корни неверны. Они должны следовать формату ниже:

MEDIA_URL = S3_URL + MEDIA_DIRECTORY
STATIC_URL = S3_URL + STATIC_DIRECTORY
MEDIA_ROOT = '/home/host/app/static_root/media'
STATIC_ROOT = '/home/host/app/static_root/static'

Примечание: измените MEDIA_ROOT а также STATIC_ROOT как ваш проект настроен.

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

Извините, не видел, что вы использовали компрессор. Попробуйте сделать следующее:

COMPRESS_URL = S3_URL + STATIC_DIRECTORY
STATIC_URL = COMPRESS_URL
MEDIA_URL = S3_URL + MEDIA_DIRECTORY
MEDIA_ROOT = '/home/host/app/static_root/media'
STATIC_ROOT = '/home/host/app/static_root/static'
Другие вопросы по тегам