2011-01-24 35 views
9

Trong Django, tôi có mô hình sau đây:Django: Làm cách nào để thay thế/ghi đè/cập nhật/thay đổi tệp của FileField?

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) 

Tôi muốn để có thể thay thế file trong FileField Video trên một mô hình đối tượng/ví dụ. Phương pháp trên tôi đã viết không hoạt động. Khi tôi xóa tệp gốc, tôi nhận được thông báo lỗi sau:

ValueError: The 'video' attribute has no file associated with it. 

Làm cách nào để thay thế tệp bằng tệp đã cập nhật và xóa tệp gốc (không cần thiết)?

Side-Note: Tôi đã tìm thấy một related issue, nhưng không có câu trả lời thỏa mãn.

Trả lời

10

Bạn có hai lựa chọn.

Tôi giả định mô hình Project của bạn chỉ là một đoạn mã.

Tùy chọn 1 là để phá vỡ mô hình của bạn để dự án không có một tệp duy nhất, mà đúng hơn là mô hình dự án được liên kết với mô hình ProjectFile. Có lẽ một-nhiều. Một dự án như nhiều ProjectFiles. Đó là, ProjectFile có một ForeigKey to Project.

Sau đó, bạn có thể thêm ProjectFile mới dựa trên một ProjectFile cũ. Bạn có thể xóa chúng và đánh lừa tất cả những gì bạn muốn. Thật vậy, bạn có thể giữ cả hai ProjectFile với một chỉ số trong đó là "hiện tại".

Tùy chọn 2 là self.video.open("w") để mở tệp để ghi. Viết lại nội dung "tại chỗ". Thay vì xóa và thay thế tệp, hãy viết lại tệp cũ bằng nội dung mới.

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) 

Điều đó có thể sẽ làm những gì bạn muốn.

Có, có vẻ như không hiệu quả. Nó thực sự không phải là xấu. Chuyển đổi mất bao giờ hết. Bản sao mất vài phút.

+0

Lựa chọn 1 thực sự có vẻ là một ý tưởng tốt. Cảm ơn! –

4

Tôi đã xem qua vấn đề này thời gian gần đây bản thân mình, và giải quyết nó một cái gì đó như thế này:

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) 
Các vấn đề liên quan