Django: как заменить/перезаписать/обновить/изменить файл FileField?
в Django, у меня есть следующие модели:
from django.db import models
from django.core.files.base import File
import os, os.path
class Project(models.Model):
video = models.FileField(upload_to="media")
def replace_video(self):
"""Convert video to WebM format."""
# This is where the conversion takes place,
# returning a path to the new converted video
# that I wish to override the old one.
video_path = convert_video()
# Replace old video with new one,
# and remove original unconverted video and original copy of new video.
self.video.delete(save=True)
self.video.save(os.path.basename(video_path), File(open(video_path ,"wb")), save=True)
os.remove(video_path)
Я хочу иметь возможность заменить файл в поле FileField видео на объекте/экземпляре модели. Описанный выше метод не работает. Как только я удаляю исходный файл, я получаю следующую ошибку:
ValueError: The 'video' attribute has no file associated with it.
Как я могу заменить файл обновленным и удалить исходный (больше не требуется)?
К: Я нашел связанный с этим вопрос, но без удовлетворительного ответа.
2 ответов
у вас есть два варианта.
Я предполагаю, что ваш Project
модель-это только фрагмент кода.
Вариант 1-разбить вашу модель так, чтобы проект не имел одного файла, а скорее модель проекта связана с моделью ProjectFile. Пожалуй, один-ко-многим. Один проект столько ProjectFiles. То есть, ProjectFile имеет ForeigKey для проекта.
затем вы можете добавить новый файл ProjectFile на основе старого файла ProjectFile. Вы можете удалить их, и дурачиться все, что хочешь. Действительно, Вы можете сохранить оба файла ProjectFile с индикатором, который является "текущим".
Вариант 2 -self.video.open("w")
открыть файл для записи. Перепишите содержимое "на месте". Вместо удаления и замены файла, перепишите старый файл с новым содержимым.
with open(video_path ,"rb") as source:
self.video.open("wb")
bytes= source.read(4096)
if bytes:
self.video.write( bytes )
bytes= source.read(4096)
Это, вероятно, сделает то, что вы хотите.
Да, это кажется неэффективным. Все не так уж плохо. Преобразование длится вечно. Копия занимает несколько минут.
недавно я сам столкнулся с этой проблемой и решил ее примерно так:
from django.db import models
from django.core.files.base import File
import os, os.path
class Project(models.Model):
video = models.FileField(upload_to="media")
def replace_video(self):
"""Convert video to WebM format."""
# This is where the conversion takes place,
# returning a path to the new converted video
# that I wish to override the old one.
video_path = convert_video()
# Replace old video with new one,
# and remove original unconverted video and original copy of new video.
old_path = self.video.path
self.video.save(os.path.basename(video_path), File(open(video_path ,"wb")), save=True)
os.remove(video_path)
os.remove(old_path)