2011-09-22 130 views
62

這是我的模型。我想要做的就是生成一個新文件,並覆蓋現有每當模型實例保存:Django - 如何創建一個文件並將其保存到模型的FileField?

class Kitten(models.Model): 
    claw_size = ... 
    license_file = models.FileField(blank=True, upload_to='license') 

    def save(self, *args, **kwargs): 
     #Generate a new license file overwriting any previous version 
     #and update file path 
     self.license_file = ??? 
     super(Request,self).save(*args, **kwargs) 

我看到大量的文件如何上傳文件。但是,如何生成一個文件,將其分配給模型字段並讓Django將它存儲在正確的位置?

回答

91

您想查看Django文檔中的FileField and FieldFile,尤其是FieldFile.save()

基本上,一個字段聲明爲FileField,訪問時,給你FieldFile類的實例,它爲您提供了幾種方法來與底層文件進行交互。所以,你需要做的是:

self.license_file.save(new_name, new_contents) 

其中new_name是你希望分配的文件名和new_contents是該文件的內容。請注意0​​必須是django.core.files.Filedjango.core.files.base.ContentFile的實例(有關詳細信息,請參閱指定手冊的鏈接)。有兩種選擇,可以歸結爲:

# Using File 
f = open('/path/to/file') 
self.license_file.save(new_name, File(f)) 
# Using ContentFile 
self.license_file.save(new_name, ContentFile('A string with the file content')) 
+1

好吧,我認爲這會工作,但我進入某種遞歸循環的調用,在保存方法。它只是不斷創建文件。 – Greg

+8

對於遞歸問題,我必須使用arg save = False調用self.license_file.save。 – Greg

+0

@Greg謝謝你,遞歸問題真的很煩人。 – laike9m

18

接受的答案無疑是一個很好的解決方案,但這裏是我去有關生成CSV並從視圖服務的方式。

#Model 
class MonthEnd(models.Model): 
    report = models.FileField(db_index=True, upload_to='not_used') 

import csv 
from os.path import join 

#build and store the file 
def write_csv(): 
    path = join(settings.MEDIA_ROOT, 'files', 'month_end', 'report.csv') 
    f = open(path, "w+b") 

    #wipe the existing content 
    f.truncate() 

    csv_writer = csv.writer(f) 
    csv_writer.writerow(('col1')) 

    for num in range(3): 
     csv_writer.writerow((num,)) 

    month_end_file = MonthEnd() 
    month_end_file.report.name = path 
    month_end_file.save() 

from my_app.models import MonthEnd 

#serve it up as a download 
def get_report(request): 
    month_end = MonthEnd.objects.get(file_criteria=criteria) 

    response = HttpResponse(month_end.report, content_type='text/plain') 
    response['Content-Disposition'] = 'attachment; filename=report.csv' 

    return response 

思想,而把這個這裏我花了擺弄得到所有期望的行爲(覆蓋現有文件,保存到正確的位置,而不是創建重複文件等)的一點點很值得。

的Django 1.4.1

的Python 2.7.3

0

感謝@tawmas。除此之外,

如果我在打開文件時未指定文件模式,則出現錯誤。所以,

f = open('/path/to/file', 'r') 

對於ZIP文件的類型,

f = open('/path/to/file.zip', 'rb') 
相關問題