Files
klangkarte/backend/common/form/audio_file.py
2024-06-27 22:41:39 +02:00

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)