2011-09-22 49 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

FileField and FieldFileをDjangoのドキュメント、特にFieldFile.save()で見たいと思っています。

基本的には、FileFieldとして宣言されたフィールドは、FieldFileのインスタンスを提供します。このインスタンスは、基礎となるファイルと対話するいくつかのメソッドを提供します。だから、何をする必要がある:

new_nameはあなたが割り当てられ、 new_contentsは、ファイルの内容で希望のファイル名である
self.license_file.save(new_name, new_contents) 

new_contentsは、django.core.files.Fileまたはdjango.core.files.base.ContentFileのいずれかのインスタンスでなければならないことに注意してください(詳細は、マニュアルへのリンクを参照)。 2つの選択肢がに煮詰める:

# 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

再帰的な問題については、私はself.license_file.saveをarg save = Falseと呼ぶ必要があります。 – 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 

は、それは私に(重複したファイルなどを作成していない、適切な場所に格納し、既存のファイルを上書きする)すべての望ましい動作を取得するためにいじるの少しを取ったとして、ここではこれを入れながら、それは価値があったと思いました。

ジャンゴ1.4.1

のPython 2.7.3

0

おかげ@tawmas。それに加えて、

私はファイルを開くときにファイルモードを指定しなければエラーになります。だから、ファイルのZIPの種類については

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

、[OK]を

f = open('/path/to/file.zip', 'rb') 
関連する問題