|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
# Erik Stein <code@classlibrary.net>, 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 django.utils.functional import curry
|
|
|
|
|
|
|
|
from assetkit.files.storage import ProtectedMediaAssetStorage
|
|
|
|
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<br />%(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):
|
|
|
|
storage = kwargs.get('storage', MEDIA_ASSET_STORAGE)
|
|
|
|
kwargs['storage'] = storage
|
|
|
|
|
|
|
|
upload_func = kwargs.get('upload_to', DEFAULT_UPLOAD_TO)
|
|
|
|
if callable(upload_func):
|
|
|
|
kwargs['upload_to'] = curry(upload_func, storage=storage)
|
|
|
|
else:
|
|
|
|
kwargs['upload_to'] = upload_func
|
|
|
|
|
|
|
|
# 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 = storage.FILENAME_MAX_LENGTH + 2 \
|
|
|
|
+ len(storage.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': self.storage.FILENAME_MAX_LENGTH,
|
|
|
|
}
|
|
|
|
kwargs.update(defaults) # Force our values
|
|
|
|
return super(MediaAssetField, self).formfield(**kwargs)
|