在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 video 中的文件。我写的上述方法不起作用。删除原始文件后,出现以下错误:
ValueError: The 'video' attribute has no file associated with it.
如何用更新的文件替换文件,并删除原文件(不再需要)?
Side-Note :我找到了related issue,但没有令人满意的答案。
答案 0 :(得分:11)
你有两个选择。
我假设您的Project
模型只是一段代码。
选项1是打破您的模型,以便项目没有单个文件,而是项目模型与ProjectFile模型相关联。也许一对多。一个项目尽可能多的ProjectFiles。也就是说,ProjectFile有一个ForeigKey to Project。
然后,您可以基于旧的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)
这可能会做你想要的。
是的,似乎效率低下。这真的不是那么糟糕。转换需要永远。副本需要时间。
答案 1 :(得分:4)
我最近自己遇到了这个问题,并解决了类似这样的问题:
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)