Django: How to replace/overwrite/update/change a file of FileField?

前端 未结 2 1197
臣服心动
臣服心动 2020-12-16 00:53

In Django, I have the following model:

from django.db import models
from django.core.files.base import File
import os, os.path

class Project(models.Model):
         


        
相关标签:
2条回答
  • 2020-12-16 01:41

    I came across this problem recently myself, and solved it something like this:

    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)
    
    0 讨论(0)
  • 2020-12-16 01:55

    You have two choices.

    I'll assume your Project model is only a snippet of code.

    Option 1 is to break your model down so that a Project does not have a single file, but rather a Project model is associated with a ProjectFile model. Perhaps one-to-many. One Project as many ProjectFiles. That is, ProjectFile has a ForeigKey to Project.

    Then you can add new ProjectFile based on an old ProjectFile. You can delete them, and fool around all you want. Indeed, you can keep both ProjectFile's with an indicator of which is "current".

    Option 2 is to self.video.open("w") to open the file for writing. Rewrite the contents "in place". Instead of deleting and replacing the file, rewrite the old file with the new content.

    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)
    

    That will probably do what you want.

    Yes, it seems inefficient. It's really not that bad. The conversion takes for ever. The copy takes moments.

    0 讨论(0)
提交回复
热议问题