У меня есть следующая модель:
class Class(models.Model):
title = models.CharField(max_length = 60)
video = models.FileField(
upload_to = class_files_custom_upload,
validators = [
FileExtensionValidator(['mp4', 'webm', 'mpg', 'mpeg', 'ogv']),
]
)
section = models.ForeignKey(Section, on_delete = models.CASCADE)
created = models.DateTimeField(auto_now_add = True)
class Meta:
verbose_name = 'clase'
verbose_name_plural = 'clases'
ordering = ['created']
def __str__(self):
return self.title
Я создаю экземпляр этой модели, но если я обновлю поле video
другим файлом любого экземпляра, предыдущий сохраненный файл будет потерян и файл занимает место, и я хочу избежать его, удаляя файл.
Для этого я настраиваю загрузку файла, помещая вызываемый элемент в upload_to
:
def class_files_custom_upload(instance, filename):
try:
old_instance = Class.objects.get(id = instance.id)
old_instance.video.delete()
except Class.DoesNotExist:
pass
return os.path.join('courses/videos', generate_secure_filename(filename))
Таким образом, я достигаю своей цели. Но у меня есть несколько моделей, которые сохраняют мультимедийные файлы, и для каждой из них мне нужно настроить загрузку файла, практически выполняя функцию, почти равную class_files_custom_upload
, и код повторяется, и это совсем не оптимально.
Я пытался создать функцию многократного использования, которая соответствует цели функции class_files_custom_upload
, в различных полях, таких как ImageField
и FileField
, но я не могу этого сделать, поскольку функция получает только 2 параметра, instance
и filename
, что является слишком малым количеством данных для его достижения.
Единственный способ, которым мне удалось создать эту "функцию", которая соответствует цели и может быть повторно использована, - это создать валидатор:
def delete_orphaned_media_file(value):
old_instance = value.instance.__class__.objects.get(pk = value.instance.pk)
media_file_field = getattr(old_instance, value.field.name)
if not media_file_field.name == value.name: media_file_field.delete()
И это работает, но в конце концов это «валидатор», «валидатор» должен проверять поле, а не «это». У меня вопрос: это хорошая практика?
Есть ли лучшая альтернатива моему решению? но эта альтернатива отвечает цели повторного использования.
Любое предложение помогает моему обучению, спасибо.