【问题标题】:django-storages with multiple S3 Buckets具有多个 S3 存储桶的 django-storages
【发布时间】:2016-07-01 05:59:46
【问题描述】:

我正在使用 AWS,我的应用程序中会有不同的存储桶。我也在使用 Django-Storages。有没有办法指定我要将文件上传到哪个存储桶(例如,作为 Save() 函数中的参数或其他什么?)

看到了这个Django - Error importing storages.backends,但是不明白应该怎么用?!

【问题讨论】:

    标签: django amazon-web-services python-django-storages


    【解决方案1】:

    对于 S3Boto3Storage 使用这个:

    media_file = models.FileField('media file', storage=S3Boto3Storage(bucket_name='media_bucket'), upload_to='media', blank=True)
    

    【讨论】:

      【解决方案2】:

      只需在 settings.py 中使用 PRIVATE_BUCKET_NAME='bucket name' 提及另一个存储桶名称。

      创建一个覆盖 S3BotoStorage 并且可以序列化为迁移文件的自定义类。

      s3_storage = S3MediaStorage() 类创建一个对象并将其存储在 MyModel 的 file1 字段中

      from storages.backends.s3boto import S3BotoStorage
      from django.conf import settings
      
      @deconstructible
      class S3MediaStorage(S3BotoStorage):
          def __init__(self, *args, **kwargs):
              kwargs['bucket'] = getattr(settings, 'PRIVATE_BUCKET_NAME')
              super(S3MediaStorage, self).__init__(*args, **kwargs)
      
      s3_storage = S3MediaStorage()
      
      class MyModel(models.Model):
          file = models.FileField()
          file1 = models.FileField(storage=s3_storage)
      

      【讨论】:

        【解决方案3】:

        S3BotoStorage 将存储桶名称作为参数。如果没有给出,它将使用AWS_STORAGE_BUCKET_NAME 设置。这意味着如果您想使用DEFAULT_FILE_STORAGES3BotoStorage 设为默认存储后端,那么它必须使用默认存储桶。

        但是,您也可以在字段级别分配存储:

        from django.db import models
        from storages.backends.s3boto import S3BotoStorage
        
        class MyModel(models.Model):
            file_1 = models.FileField() # Uses default storage
            file_2 = models.FileField(storage=S3BotoStorage(bucket='other-bucket'))
        

        编辑

        评论已经失控,所以我会更新我的答案。基于实例更改存储后端的参数并不是 Django 存储 API 的设计目的。存储后端不知道模型实例,因为存储可以在模型上下文之外使用,例如静态文件。并非完全不合理,但这不是 Django 或 django-storages 旨在解决的用法。我不希望您找到可以为您处理此问题的存储后端。

        文档描述了如何手动管理文件:https://docs.djangoproject.com/en/1.9/topics/files/#storage-objects 至少您需要将存储桶存储在您保存文件的某个位置,以便以后在查询模型时可以找到它。

        【讨论】:

        • 很好...所以我不需要像这里显示的那样覆盖? stackoverflow.com/questions/9430770/…我可以像你刚才给我看的那样把桶传过去?!
        • 是的,对于这个用例,您不需要,因为您可以传递存储桶名称。
        • 快速问号:在答案中,您传递的是静态存储桶名称。我们有没有机会动态地传递它?由于存储桶名称将在运行时解析...
        • No 不在模型定义中。为此,您需要 S3BotoStorage 的子类,可能还需要 FileField,具体取决于您打算如何在运行时解析存储桶名称。
        • 在某些时候,此参数似乎已更改为bucket_name,使用bucket 将返回错误:django.core.exceptions.ImproperlyConfigured: Invalid setting 'bucket' for S3Boto3Storage。见django-storages 来源:github.com/jschneier/django-storages/blob/…
        【解决方案4】:

        另一个解决方案,如果你想在运行时指定存储桶,你可以在调用模型的 save() 方法之前这样做。

        按照上面的例子:

        from django.db import models
        from storages.backends.s3boto import S3BotoStorage
        
        class MyModel(models.Model):
            file_1 = models.FileField() # Uses default storage
            file_2 = models.FileField()
        

        在保存模型时的视图中,您可以在该字段上指定存储。

        my_file_model = MyModel()
        my_file_model.file_2.storage = S3BotoStorage(bucket="your-bucket-name")
        my_file_model.save()
        

        这样,file_2 将保存在您指定的存储桶中,file_1 将使用您的默认存储桶。

        【讨论】:

        • 这很酷,但在分配新存储系统之前要小心分配文件。否则默认存储将覆盖您的自定义存储。
        • 如果这是一个愚蠢的问题,我很抱歉,我是 django 的新手。您如何建议为上述示例编写视图,我们不能简单地将其保存在模型中吗?
        • 我用这个方法覆盖了save(): def save(self, *args, **kwargs): self.file_field.storage = MyS3Boto3Storage(bucket_name=self.bucket_name()) super().save(*args, **kwargs) self.bucket_name() - 获取桶名的函数取决于模型选项。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-02
        • 2016-12-28
        • 2017-12-12
        • 1970-01-01
        • 2021-08-14
        相关资源
        最近更新 更多