django-generic-storage

Generic Storage Class for Django

Control Django Storage per Model Field based on Settings Configuration

from django.conf import settings
from django.utils.module_loading import import_string
from django.utils.deconstruct import deconstructible

def get_storage_class(import_path=None):
    return import_string(import_path or settings.DEFAULT_FILE_STORAGE)

@deconstructible
class GenericStorage(object):
    """
    Generic storage class which takes in a key and looks up a storage defined
    in STORAGES in django settings. If setting does not exist then use the default
    storage.
    """
    def __init__(self, storage_key):
        self.storage_key = storage_key
        self._storage = self.build_storage()

    def __getattr__(self, name):
        """Proxy to underlying storage class"""
        return getattr(self._storage, name)

    def get_storage_from_settings(self):
        """Fetch backend from settings"""
        storage_key = self.storage_key
        storage_backend = None

        if storage_key and hasattr(settings, 'STORAGES'):
            try:
                storage_entry = settings.STORAGES[self.storage_key]
            except KeyError:
                msg = 'Could not find storage {}'.format(self.storage_key)
                raise KeyError(msg)
            storage_backend = storage_entry.get('BACKEND')

        return storage_backend

    def build_storage(self):
        """Construct Storage"""
        storage_backend = self.get_storage_from_settings()
        return get_storage_class(storage_backend)()

settings

STORAGES = {
    'public-media': {
        'BACKEND': 'whatever.storages.backends.s3boto3.PublicMediaStorage',
    },
    'private-media': {
        'BACKEND': 'whatever.storages.backends.s3boto3.PrivateMediaStorage',
    }
}

storages
from storages.backends.s3boto3 import S3Boto3Storage


class PublicMediaStorage(S3Boto3Storage):
    """S3 Public Storage"""
    bucket_name = 'media.whatever.com'
    default_acl = 'private' # made public through aws bucket policy
    file_overwrite = False
    location = 'media'
    querystring_auth = False
    region_name = 'us-west-2'


class PrivateMediaStorage(S3Boto3Storage):
    """S3 Private Storage"""
    bucket_name = 'media.whatever.com'
    default_acl = 'private'
    file_overwrite = False
    location = 'media'
    querystring_expire = 60 * 60
    region_name = 'us-west-2'
example

document = models.FileField(upload_to,...,storage=GenericStorage('public-media'))