From 618cdb94315851816a247a6b8a837dc0c9523251 Mon Sep 17 00:00:00 2001 From: benzkji Date: Tue, 20 Jun 2017 11:34:34 +0200 Subject: [PATCH] initial signals and utils --- filer_addons/filer_signals/__init__.py | 0 filer_addons/filer_signals/conf.py | 20 ++++ filer_addons/filer_signals/models.py | 101 ++++++++++++++++++ filer_addons/filer_utils/__init__.py | 0 .../generate_folder_and_filename.py | 24 +++++ 5 files changed, 145 insertions(+) create mode 100644 filer_addons/filer_signals/__init__.py create mode 100644 filer_addons/filer_signals/conf.py create mode 100644 filer_addons/filer_signals/models.py create mode 100644 filer_addons/filer_utils/__init__.py create mode 100644 filer_addons/filer_utils/generate_folder_and_filename.py diff --git a/filer_addons/filer_signals/__init__.py b/filer_addons/filer_signals/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/filer_addons/filer_signals/conf.py b/filer_addons/filer_signals/conf.py new file mode 100644 index 0000000..62de1b3 --- /dev/null +++ b/filer_addons/filer_signals/conf.py @@ -0,0 +1,20 @@ + +from django.conf import settings + + +FILER_ADDONS_DUPLICATE_HANDLING = getattr( + settings, 'FILER_ADDONS_DUPLICATE_HANDLING', { + 'prevent': True, + 'same_folder_required': True, + 'same_filename_required': True, + 'rename_files': True, + } +) + + +FILER_ADDONS_UNFILED_HANDLING = getattr( + settings, 'FILER_ADDONS_UNFILED_HANDLING', { + 'move_unfiled': True, + 'default_folder_name': '0 - Direct Uploads', + } +) diff --git a/filer_addons/filer_signals/models.py b/filer_addons/filer_signals/models.py new file mode 100644 index 0000000..3889157 --- /dev/null +++ b/filer_addons/filer_signals/models.py @@ -0,0 +1,101 @@ +from __future__ import unicode_literals +import os + +from django.db.models.signals import pre_save, post_save +from django.dispatch import receiver +from django.core.files.base import File as DjangoFile +from filer.models import File, Folder +from filer.utils.files import get_valid_filename + + +from . import conf + + +def check_rename(instance, old_name=None): + """ + do the rename + :param instance: filer file instance + :return: + """ + # print "check rename" + if instance.id and instance.file: + if old_name is None: + old_instance = File.objects.get(pk=instance.id) + old_name = old_instance.file.name + old_name = os.path.basename(old_name) + new_name = get_valid_filename(instance.original_filename) + if not old_name == new_name: + # rename! + # print "do rename: %s to %s" % (old_name, new_name) + new_file = DjangoFile(open(instance.file.path, mode='rb')) + instance.file.delete(False) # remove including thumbs + instance.file.save(new_name, new_file, save=False) + # do it here, original_filename doesnt seem to be updated correctly else! + instance.save() + + +@receiver(post_save, sender='filer.File') +def filer_duplicates_and_rename(sender, instance, **kwargs): + """ + check for duplicates, dont allow them! + as this is post save, it will ELIMINATE ALL DUPLICATES of a file, if there are! + this can be quite dangerous, but also be wonderfull ;-) + """ + # print "check duplicates" + file_obj = instance + duplicates = File.objects.filter(sha1=file_obj.sha1, folder=file_obj.folder) + duplicates = duplicates.exclude(pk=file_obj.id) + if len(duplicates): + # print "duplicates found (post save):" + # print duplicates + duplicate = None + for file in duplicates: + if file.file: + duplicate = file + if duplicate is None: + # duplicate without file is not what we can use! + return + instance.delete() + duplicate = duplicates[0] + old_name = duplicate.file.name + instance.id = duplicate.id + instance.file = duplicate.file + instance.name = duplicate.name + instance.name = duplicate.name + instance.description = duplicate.description + if hasattr(duplicate, 'subject_location'): + instance.subject_location = duplicate.subject_location + # set some more fields from duplicate, if they are filled?! + # arf dont touch django magic + # instance._uncommitted_filefields = [] + # instance._state = duplicate._state + instance.save() + check_rename(instance, old_name=old_name) + else: + # when updating a file in a files detail view, it already has the new, correct name + # leaving this here, for example when manipulating files (and original_filename) programmatically. + check_rename(instance) + + +@receiver(post_save, sender='filer.File') +def filer_unfiled_to_folder(sender, instance, **kwargs): + """ + check if a file is unfiled, if yes, put into default folder. + """ + if not conf.FILER_ADDONS_UNFILED_HANDLING.get('move_unfiled', None): + return + if not instance.folder: + default_folder_name = conf.FILER_ADDONS_UNFILED_HANDLING.get( + 'default_folder_name', + 'Unfiled', + ) + default_folder_list = Folder.objects.filter(name=default_folder_name) + if default_folder_list.count() > 0: + default_folder = default_folder_list[0] + else: + default_folder = Folder(name=default_folder_name) + default_folder.save() + instance.folder = default_folder + instance.save() + + diff --git a/filer_addons/filer_utils/__init__.py b/filer_addons/filer_utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/filer_addons/filer_utils/generate_folder_and_filename.py b/filer_addons/filer_utils/generate_folder_and_filename.py new file mode 100644 index 0000000..dbe3bb8 --- /dev/null +++ b/filer_addons/filer_utils/generate_folder_and_filename.py @@ -0,0 +1,24 @@ +import os +import uuid + +from filer.utils.files import get_valid_filename + + +def no_subfolders(instance, filename): + """ + for the minimalist + attention, in case of filename collisions, files might get renamed to + "originalname_huievad676asd.ext", which is automatically done by the + django storage backend + """ + return get_valid_filename(filename) + + +def short_uuid4(instance, filename): + """ + short (8chars) uuid4 path and the filename + https://stackoverflow.com/a/13484764/1029469 + should be safe enough for most cases + """ + filename = get_valid_filename(filename) + return os.path.join(uuid.uuid4()[:8], filename)