You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.7 KiB
95 lines
3.7 KiB
# -*- 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 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<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): |
|
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)
|
|
|