71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib.admin.widgets import AdminFileWidget
|
|
from django.core.validators import FileExtensionValidator
|
|
from django.db import models
|
|
from django.forms import FileInput, widgets
|
|
|
|
from common.validators import MaxFilesizeValidator, readableToInt
|
|
|
|
MAX_UPLOAD_SIZE = '20 MB'
|
|
|
|
|
|
class AudioFileWidget(widgets.ClearableFileInput):
|
|
template_name = 'forms/audio-file.html'
|
|
|
|
class Media:
|
|
js = ['admin/file-upload-validator.js']
|
|
|
|
def get_context(self, name, value, attrs):
|
|
context = super().get_context(name, value, attrs)
|
|
context['MEDIA_URL'] = settings.MEDIA_URL
|
|
return context
|
|
|
|
|
|
class AudioField(forms.FileField):
|
|
widget = AudioFileWidget
|
|
default_validators = [
|
|
FileExtensionValidator(['mp3']),
|
|
MaxFilesizeValidator(MAX_UPLOAD_SIZE)
|
|
]
|
|
|
|
def widget_attrs(self, widget):
|
|
attrs = super().widget_attrs(widget)
|
|
if isinstance(widget, FileInput) and 'accept' not in widget.attrs:
|
|
attrs.setdefault('accept', 'audio/mpeg') # audio/*
|
|
if isinstance(widget, AudioFileWidget):
|
|
attrs.update({
|
|
'data-upload-limit': readableToInt(MAX_UPLOAD_SIZE),
|
|
'data-upload-limit-str': MAX_UPLOAD_SIZE,
|
|
'onchange': 'validate_upload_limit(this)',
|
|
})
|
|
return attrs
|
|
|
|
|
|
class AudioFileField(models.FileField):
|
|
__del_file_on_save = False
|
|
|
|
def formfield(self, **kwargs):
|
|
if kwargs['widget'] is AdminFileWidget:
|
|
# Override admin widget. Defined by AudioField anyway
|
|
del kwargs['widget']
|
|
return super().formfield(**{'form_class': AudioField, **kwargs})
|
|
|
|
def save_form_data(self, instance, data):
|
|
if data is False:
|
|
self.__del_file_on_save = True
|
|
super().save_form_data(instance, data)
|
|
|
|
def pre_save(self, model_instance, add):
|
|
if self.__del_file_on_save:
|
|
self.__del_file_on_save = False
|
|
self.deletePreviousFile(model_instance)
|
|
return super().pre_save(model_instance, add)
|
|
|
|
def deletePreviousFile(self, instance: models.Model):
|
|
if not instance.pk:
|
|
return
|
|
prev = instance.__class__.objects.get(pk=instance.pk)
|
|
fileField = getattr(prev, self.attname)
|
|
fileField.delete(save=False)
|