2011-09-22 29 views
62

Đây là mô hình của tôi. Những gì tôi muốn làm là tạo một tệp mới và ghi đè lên tệp hiện có bất kỳ khi nào một phiên bản mẫu được lưu:Django - cách tạo tệp và lưu tệp đó vào FileField của mô hình?

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) 

Tôi thấy rất nhiều tài liệu về cách tải tệp lên. Nhưng làm thế nào để tôi tạo ra một tập tin, gán nó vào một lĩnh vực mô hình và có Django lưu trữ nó ở đúng nơi?

Trả lời

91

Bạn muốn xem FileField and FieldFile trong tài liệu Django và đặc biệt là FieldFile.save().

Về cơ bản, trường được khai báo là FileField, khi được truy cập, cung cấp cho bạn một phiên bản của lớp FieldFile, cung cấp cho bạn một số phương pháp để tương tác với tệp cơ bản. Vì vậy, những gì bạn cần làm là:

self.license_file.save(new_name, new_contents) 

nơi new_name là tên file bạn chúc các giao và new_contents là nội dung của tập tin. Lưu ý rằng new_contents phải là một phiên bản của django.core.files.File hoặc django.core.files.base.ContentFile (xem các liên kết đã cung cấp cho hướng dẫn sử dụng để biết chi tiết). Hai lựa chọn đun sôi xuống:

câu trả lời
# 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

Ok, tôi nghĩ rằng sẽ làm việc nhưng tôi nhận được vào một số loại vòng lặp đệ quy gọi rằng trong phương pháp tiết kiệm. Nó chỉ tiếp tục tạo ra các tập tin mãi mãi. – Greg

+8

Đối với các vấn đề đệ quy tôi phải gọi self.license_file.save với arg save = False. – Greg

+0

@Greg cảm ơn bạn, vấn đề đệ quy thực sự gây phiền nhiễu. – laike9m

18

Được chấp nhận chắc chắn là một giải pháp tốt, nhưng đây là cách tôi đã đi về tạo ra một CSV và phục vụ nó từ một cái nhìn.

#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 

Nghĩ rằng nó là giá trị trong khi đặt này ở đây vì nó đã cho tôi một chút không quan trọng để có được tất cả các hành vi mong muốn (ghi đè lên tập tin hiện có, tàng trữ để đúng chỗ, không tạo ra các file trùng lặp vv).

Django 1.4.1

Python 2.7.3

0

Cảm ơn @tawmas. Ngoài ra,

Tôi gặp lỗi nếu tôi không chỉ định chế độ tệp trong khi mở tệp. Vì vậy,

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

Đối với loại ZIP file,

f = open('/path/to/file.zip', 'rb') 
Các vấn đề liên quan