# -*- coding: utf-8 -*- from __future__ import unicode_literals # Erik Stein , 2016 from django import forms from django.contrib.admin.widgets import AdminFileWidget from django.db import models from django.db.models.fields.files import FileDescriptor from assetkit.files.storage import ProtectedMediaAssetStorage, FILENAME_MAX_LENGTH, ORIGINAL_FILE_PREFIX from .utils import get_upload_path # TODO Define the central storage somewhere more central MEDIA_ASSET_STORAGE = ProtectedMediaAssetStorage() DEFAULT_UPLOAD_TO = get_upload_path class MediaAssetFileWidget(AdminFileWidget): """ Widget which understands ProtectedMediaAssetStorage (knows that the url property is not relevant), also does not provide a link to the original file. # TODO Only admin access to the original file, if permissions apply # TODO Add permission "allowed to view original file" """ # template_with_initial = ( # '%(initial_text)s: %(initial)s ' # '%(clear_template)s
%(input_text)s: %(input)s' # ) def is_initial(self, value): # Checks for 'name' instead of 'url' property return bool(value and hasattr(value, 'name')) # def get_template_substitution_values(self, value): # # Does not use value.url # return { # 'initial': conditional_escape(value), # } class MediaAssetFileDescriptor(FileDescriptor): # TODO Assign metadata fields like width/height def __set__(self, instance, value): previous_file = instance.__dict__.get(self.field.name) super(MediaAssetFileDescriptor, self).__set__(instance, value) # TODO Check if previous_file is actually None in our case; remove comment # To prevent recalculating image dimensions when we are instantiating # an object from the database (bug #11084), only update dimensions if # the field had a value before this assignment. Since the default # value for FileField subclasses is an instance of field.attr_class, # previous_file will only be None when we are called from # Model.__init__(). The ImageField.update_dimension_fields method # hooked up to the post_init signal handles the Model.__init__() cases. # Assignment happening outside of Model.__init__() will trigger the # update right here. if previous_file is not None: pass # self.field.update_dimension_fields(instance, force=True) # TODO MediaAssetFormField unused class MediaAssetFormField(forms.FileField): widget = MediaAssetFileWidget class MediaAssetField(models.FileField): # The descriptor to use for accessing the attribute off of the class. description_class = MediaAssetFileDescriptor def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, *args, **kwargs): kwargs['storage'] = kwargs.get('storage', MEDIA_ASSET_STORAGE) kwargs['upload_to'] = kwargs.get('upload_to', DEFAULT_UPLOAD_TO) # Field max length is the length of the file name plus the # string ORIGINAL_FILE_PREFIX, two slashes and the uuid. The filename # is shortened in the get_upload_path function. field_max_length = FILENAME_MAX_LENGTH + 2 \ + len(ORIGINAL_FILE_PREFIX) \ + 32 # uuid_hex kwargs['max_length'] = kwargs.get('max_length', field_max_length) super(MediaAssetField, self).__init__(verbose_name, name, **kwargs) def formfield(self, **kwargs): defaults = { # 'form_class': MediaAssetFormField, 'widget': MediaAssetFileWidget, 'max_length': FILENAME_MAX_LENGTH, } kwargs.update(defaults) # Force our values return super(MediaAssetField, self).formfield(**kwargs)