Work in progress: django-imagekit but for all types of media files (movies, PDFs etc.). + private media
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.

103 lines
3.9 KiB

10 years ago
# -*- 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
10 years ago
from assetkit.files.storage import ProtectedMediaAssetStorage
from .utils import get_upload_path
10 years ago
# TODO Define the central storage somewhere more central
MEDIA_ASSET_STORAGE = ProtectedMediaAssetStorage()
10 years ago
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
10 years ago
# 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'
# )
10 years ago
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),
# }
10 years ago
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
10 years ago
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)
10 years ago
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,
10 years ago
}
kwargs.update(defaults) # Force our values
return super(MediaAssetField, self).formfield(**kwargs)