2021-03-12 13:45:07 +11:00

87 lines
2.8 KiB
Python

from django.core.files.storage import Storage
from django.conf import settings
'''
TODO: Create a signal to remove instances from cache if modified
'''
class MultiStorage(Storage):
''' Django storage class that proxies multiple storage classes.
Uses a name prefix to determine store e.g. 'images:foo/bar.jpg'
'''
def __init__(self, config=None):
self.config = config or getattr(settings, 'BRING_YOUR_OWN_STORAGE', {})
self._cache = {}
def get_storage(self, name):
if name not in self._cache:
config = self.config[name]
self._cache[name] = get_storage_class(config['storage'])(**config['settings'])
return self._cache[name]
def split(self, name):
return name.split("/", 1)
def _proxy(self, method, name, *args, **kwargs):
print('PROXY', method, name, *args, **kwargs)
storage, p = self.split(name)
result = getattr(self.get_storage(storage), method)(p, *args, **kwargs)
print("RESULT", result)
return result
def _proxy_name(self, method, name, *args, **kwargs):
print('PROXY_NAME', method, name, *args, **kwargs)
storage, p = self.split(name)
result = getattr(self.get_storage(storage), method)(p, *args, **kwargs)
print("RESULT", result)
return f"{storage}/{result}"
def _open(self, name, mode='rb'):
return self._proxy('_open', name, mode)
def _save(self, name, content, max_length=None):
return self._proxy_name('_save', name, content, max_length)
def exists(self, name):
return self._proxy('exists', name)
def delete(self, name):
return self._proxy('delete', name)
def url(self, name):
return self._proxy('url', name)
def get_accessed_time(self, name):
return self._proxy('get_accessed_time', name)
def get_alternative_name(self, file_root, file_ext):
return self._proxy_name('get_alternative_name', file_root, file_ext)
def get_available_name(self, name, max_length=None):
return self._proxy_name('get_available_name', name, max_length)
def get_modified_time(self, name):
return self._proxy('get_modified_time', name)
def get_valid_name(self, name):
return self._proxy_name('get_valid_name', name)
class BYOStorage(MultiStorage):
''' Database driven Bring-Your-Own-Storage
Multiple storages can
'''
def get_storage(self, name):
if name not in self._cache:
# use storage from config by default
if name in self.config:
return super(BYOStorage, self).get_storage(name)
from .models import UserStorage
obj = UserStorage.objects.get(name=name)
self._cache[name] = obj.instance()
return self._cache[name]