Django只在生产环境中使用私有S3存储

2024-05-23 13:37:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经将django restapi设置为在调试模式下使用本地存储,在生产环境中使用S3存储。这对于公共文件很有效,因为我重写了DEFAULT_FILE_STORAGE,如下所示:

if IS_DEBUG:
    DEFAULT_FILE_STORAGE = 'api.storage_backends.PublicMediaStorage'

每个FileField都会自动使用它。现在我想以同样的方式使用私有S3存储,但是因为我必须显式地定义存储(FileField(storage=PrivateMediaStorage())),所以总是使用S3存储。在

在调试模式下,如何使用本地存储而不是S3存储?在

PS:我已经考虑过将模型更改为使用FileField,或者根据调试模式使用带或不带显式存储的FileField。这并没有完全解决我的问题,因为我的迁移是在调试模式下创建的,因此总是包含没有私有存储类的模型。在

更新: 我正在寻找一个解决方案,它可以在两个环境中共享相同的迁移,并且只能在运行时延迟地实例化实际的storageclass。就像django已经处理了DEFAULT_FILE_STORAGE。在


Tags: 文件djangodebug模型restapidefaultifs3
2条回答

这听起来有点棘手,那就是在一个项目中同时拥有公共私有媒体存储。在

下面的示例假设您使用的是django storages,但是不管怎样,该技术都应该起作用。在

通过扩展S3BotoStorage类来定义私有存储。在

如果使用S3,最好将privatepublicpublic存储在不同的S3存储桶中。此自定义存储允许您通过设置指定此参数。在

# yourapp.custom_storage.py

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

class S3PrivateStorage(S3BotoStorage):
    """
    Optional   
    """
    default_acl = "private"               # this does the trick

    def __init__(self):
        super(S3PrivateStorage, self).__init__()
        self.bucket_name = settings.S3_PRIVATE_STORAGE_BUCKET_NAME


# important
private_storage_class = get_storage_class(settings.PRIVATE_FILE_STORAGE)

private_storage = private_storage_class() # instantiate the storage

重要的部分是这个文件的最后2行-它声明了private_storage,以便在您的FileField中使用:

^{pr2}$

最后,在您的设置文件中,应该这样做。在

# settings.py

if DEBUG:
    # In debug mode, store everything on the filestystem
    DEFAULT_FILE_STORAGE = 'django.files.storage.FileSystemStorage'
    PRIVATE_FILE_STORAGE = 'django.files.storage.FileSystemStorage'
else:
    # In production store public things using S3BotoStorage and private things
    # in a custom storage
    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
    PRIVATE_FILE_STORAGE = 'yourapp.custom_storage.S3PrivateStorage'

最后一条不请自来的建议是:将存储设置从调试模式中分离出来,并允许在环境变量中指定上述所有参数,这通常很有用。在某些时候,您可能希望使用类似生产的存储配置在调试模式下运行应用程序。在

最好的解决方案是使用FileField而不使用显式的^{类。

# settings.py

if DEBUG:
    DEFAULT_FILE_STORAGE = 'api.storage_backends.PublicMediaStorage'
else:
    DEFAULT_FILE_STORAGE = 'api.storage_backends.PrivateMediaStorage'


# models.py
class Foo(models.Model):
    file = models.FileField() # without storage

在文件上载过程中,Django将以lazy方式调用DEFAULT_FILE_STORAGE类。

这些设置不会使用storage参数创建迁移文件


更新-1

如果您想对存储进行更多控制,请创建您自己的自定义文件字段并在模型中连接起来

^{pr2}$

相关问题 更多 >