Initial commit

This commit is contained in:
Tris
2021-03-12 11:08:40 +11:00
commit 3f6046fed6
11 changed files with 173 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
__VERSION__ = 0.1
+7
View File
@@ -0,0 +1,7 @@
from django.contrib import admin
from . import models
class UserStorageAdmin(admin.ModelAdmin):
list_display = ['name', 'storage', 'owner']
admin.site.register(models.UserStorage, UserStorageAdmin)
+6
View File
@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ByostorageConfig(AppConfig):
name = 'byostorage'
verbose_name = 'Bring your own storage'
+27
View File
@@ -0,0 +1,27 @@
# Generated by Django 3.1.1 on 2021-03-11 23:11
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='UserStorage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.SlugField(help_text='Storage tag', max_length=20)),
('storage', models.CharField(help_text='Storage class for this instance', max_length=255)),
('settings_data', models.TextField(help_text='JSON dict with key/value settings')),
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
View File
+18
View File
@@ -0,0 +1,18 @@
from django.db import models
from django.core.files.storage import get_storage_class
import json
class UserStorage(models.Model):
""" A user defined storage
"""
owner = models.ForeignKey('auth.User', on_delete=models.CASCADE, null=True, blank=True)
name = models.SlugField(max_length=20, help_text="Storage tag")
storage = models.CharField(max_length=255, help_text="Storage class for this instance")
settings_data = models.TextField(help_text="JSON dict with key/value settings")
def instance(self):
return get_storage_class(self.storage)(**self.settings)
@property
def settings(self):
return json.loads(self.settings_data)
+52
View File
@@ -0,0 +1,52 @@
from django.core.files.storage import Storage
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 _open(self, name, mode='rb'):
storage, p = self.split(name)
return self.get_storage(storage)._open(p, mode)
def _proxy(self, method, name, *args, **kwargs):
storage, p = self.split(name)
sname = getattr(self.get_storage(storage), method)(name, *args, **kwargs)
if sname is not None:
return f"{storage}:{sname}"
def _save(self, name, content, max_length=None):
return self._proxy('save', name, content, max_length)
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]