django-storages + sorl_thumbnail + S3 不能很好地协同工作(URL 不匹配)

Posted

技术标签:

【中文标题】django-storages + sorl_thumbnail + S3 不能很好地协同工作(URL 不匹配)【英文标题】:django-storages + sorl_thumbnail + S3 not working well together (URLs mismatch) 【发布时间】:2012-09-21 11:57:28 【问题描述】:

我将 django-storages 和 sorl_thumbnail 一起使用,并且我将 Amazon S3 用于静态和媒体文件。我正在使用一个带有 2 个文件夹的存储桶,1 个用于静态文件夹,1 个用于媒体文件夹。

这是我的配置:

MEDIA_ROOT = '/media/'
MEDIA_URL = 'https://s3.amazonaws.com/my-bucket/media/'
STATIC_ROOT = '/static/'
STATIC_URL = 'https://s3.amazonaws.com/my-bucket/static/'
AWS_STORAGE_BUCKET_NAME = 'my-bucket'
DEFAULT_FILE_STORAGE = 'my_lib.s3utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 'my_lib.s3utils.StaticRootS3BotoStorage'

MediaRootS3BotoStorageStaticRootS3BotoStorage 定义如下:

StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage = lambda: S3BotoStorage(location='media')

当我使用 sorl_thumbnail 时,生成的缩略图位于正确的目录中:https://s3.amazonaws.com/my-bucket/media/cache 但是当 sorl_thumbnail 试图检索已经存在的缩略图时,生成的 URL 是:https://s3.amazonaws.com/my-bucket/cache,您会注意到 @987654327 @文件夹被省略。

你知道我该如何解决这个问题吗?

我知道我可以只使用 django-storages 并将我的静态和媒体文件都混合在我的存储桶中,但这对我来说有点太脏了 :)

谢谢!

【问题讨论】:

【参考方案1】:

您是否尝试将 THUMBNAIL_PREFIX 设置为 media/cache/?

http://sorl-thumbnail.readthedocs.org/en/latest/reference/settings.html#thumbnail-prefix

【讨论】:

是的,我已经试过了,谢谢。但它也不起作用,问题将是相同的,例如如果我在推送文件时设置/media/cache,则url将为/media/media/cache,检索时使用魔杖/media/cache【参考方案2】:

我遇到了同样的问题,但我找到了解决方法。

我将我的DEFAULT_FILE_STORAGE 设置回storages.backends.s3boto.S3BotoStorage,这样,当它寻找cache/ 时它不会错过,我仍然可以将我的所有文件上传到media/,并且python manage.py collectstatic 仍然有效正确,因为我仍然将其设置为StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')

希望这对您有所帮助,因为这个问题让我发疯了。

【讨论】:

感谢您的帮助!但是当我使用这些设置时,我的结果是静态文件进入 S3 上的 /static/ 文件夹,但所有上传的文件都在根文件夹中,它们不进入 /media/。有什么想法吗? 抱歉回复晚了,但请确保在您的模型中使用UPLOAD_TO='media/'。这应该把你上传的文件放在你想要的地方。 是的,我猜你在做,但我不希望这样做,否则它只会破坏 django 工作的目的:) 无论如何谢谢! @e-Jah 你找到解决方案了吗,因为我面临同样的问题 @SalmaHamed:不幸的是,我的解决方案是切换到我自己的服务器,它解决了很多麻烦!【参考方案3】:

我能够通过如下定义 MediaRootS3BotoStorageStaticRootS3BotoStorage 使其工作:

from storages.backends.s3boto import S3BotoStorage
from django.conf import settings

class StaticRootS3BotoStorage(S3BotoStorage):
    """
    Storage for static files.
    """

    def __init__(self, *args, **kwargs):
        kwargs['location'] = 'static'
        super(StaticRootS3BotoStorage, self).__init__(*args, **kwargs)


class MediaRootS3BotoStorage(S3BotoStorage):
    """
    Storage for uploaded media files.
    """

    def __init__(self, *args, **kwargs):
        kwargs['location'] = 'media'
        super(MediaRootS3BotoStorage, self).__init__(*args, **kwargs)

此链接可能会有所帮助https://github.com/jamstooks/django-s3-folder-storage

【讨论】:

上述每个__init__() 方法上的super() 方法调用了错误的类。它们应该是:super(StaticRootS3BotoStorage, self).__init__(*args, **kwargs)super(MediaRootS3BotoStorage, self).__init__(*args, **kwargs)【参考方案4】:

发现sorl-thumbnail 正在使用STATIC_URL 返回缓存的KV 图像url(在创建初始缩略图后的下一个请求上)。出现MEDIA_URL 没有影响。

不是最好的解决方案。添加了S3 路由规则。

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals>cache/</KeyPrefixEquals>
    </Condition>
    <Redirect>
      <ReplaceKeyPrefixWith>media/cache/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

【讨论】:

【参考方案5】:

我遇到了同样的问题,Salma Hamed 的解决方案结果证明对我来说是正确的。

在我们有之前

StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage = lambda: S3BotoStorage(location='media')

这导致我们的 thumbnail_kvstore 表中的“存储”值错误。此 lambda 定义不会创建新类,因此 type(StaticRootS3BotoStorage()) 返回写入表中的“storages.backends.s3boto.S3BotoStorage”。因为这些 'storage' 值用于稍后实例化存储以便在显示时获取图像 URL,这导致 S3BotoStorage() 用于此目的。所以'位置'论点丢失了。

Salma Hamed 将这些自定义存储定义为类的解决方案解决了这个问题。

谢谢!

【讨论】:

你还记得你在哪里学会使用lambda: S3BotoStorage(location='static')之前的解决方案吗?我想发表评论或更正。【参考方案6】:

IDK 为什么但 @SalmaHamed 的解决方案对我不起作用(可能是因为 django 版本的变化或其他原因)。相反,我将:MediaRootS3BotoStorage = lambda: S3Boto3Storage(location='media') 替换为: class MediaRootS3BotoStorage(S3Boto3Storage): location = 'media'

【讨论】:

以上是关于django-storages + sorl_thumbnail + S3 不能很好地协同工作(URL 不匹配)的主要内容,如果未能解决你的问题,请参考以下文章

Django-storage - 如何在上传前检查文件大小?

Django:使用 django-storage 从 S3 创建 zipfile

使用 azure 作为 Django 的存储后端(使用 django-storages)

django-storages + sorl_thumbnail + S3 不能很好地协同工作(URL 不匹配)

保存模型字段时的 Django-Storages ('`data` must be bytes, received', <class 'str'>)

使用 s3 和 django-storages 并上传图片