Skip to content

Instantly share code, notes, and snippets.

@maxpoletaev
Last active February 7, 2019 20:29
Show Gist options
  • Save maxpoletaev/dbbd9a3131b5fce819581111544105df to your computer and use it in GitHub Desktop.
Save maxpoletaev/dbbd9a3131b5fce819581111544105df to your computer and use it in GitHub Desktop.
import os
import uuid
from base64 import urlsafe_b64encode
from django.utils.deconstruct import deconstructible
from utils.base36 import base36encode
@deconstructible
class UploadPath:
def __init__(self, directory, sharding=False):
self.directory = directory
self.sharding = sharding
def get_filename(self, instance, name, ext):
return urlsafe_b64encode(uuid.uuid1().bytes).decode('ascii').strip('=') + ext
def get_directory(self, instance, filename):
return self.directory
def __call__(self, instance, filename):
name, ext = os.path.splitext(filename)
directory = self.get_directory(instance, filename)
new_filename = self.get_filename(instance, name, ext)
return os.path.join(directory, new_filename)
def __eq__(self, other):
return self.directory == other.directory
@deconstructible
class ShardedUploadPath(UploadPath):
def __init__(self, *args, **kwargs):
self.part_size = kwargs.pop('part_size', 2)
self.pk_field = kwargs.pop('pk_field', 'id')
super().__init__(*args, **kwargs)
def get_pk_value(self, instance):
value = instance
for attr in self.pk_field.split('.'):
value = getattr(value, attr)
return value
def get_directory(self, instance, filename):
pk = self.get_pk_value(instance)
assert pk is not None, 'Instance must have pk for sharded upload path'
shard = list(base36encode(pk).lower())
parts = []
for left in range(0, len(shard), self.part_size):
right = left + self.part_size
parts.append(''.join(shard[left:right]))
return os.path.join(self.directory, *parts)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment