2011-09-22 8 views
62

Ecco la mia modella. Quello che voglio fare è generare un nuovo file e sovrascrivere quello esistente ogni volta che un esempio modello è salvato:Django - come creare un file e salvarlo in FileField di un modello?

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) 

Vedo un sacco di documentazione su come caricare un file. Ma come posso generare un file, assegnarlo a un campo modello e fare in modo che Django lo memorizzi nel posto giusto?

risposta

91

Si desidera dare un'occhiata a FileField and FieldFile nei documenti Django e in particolare FieldFile.save().

In sostanza, un campo dichiarato come FileField, quando vi si accede, fornisce un'istanza della classe FieldFile, che offre diversi metodi per interagire con il file sottostante. Allora, che cosa dovete fare è:

self.license_file.save(new_name, new_contents) 

dove new_name è il nome del file che si desidera assegnare e new_contents è il contenuto del file. Si noti che new_contents deve essere un'istanza di django.core.files.File o (vedere i collegamenti forniti al manuale per i dettagli). Le due scelte si riducono a:

risposta
# 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, penso che funzionerà, ma mi sto in una sorta di ciclo ricorsivo chiamando che nel metodo di salvataggio. Continua a creare file per sempre. – Greg

+8

Per il problema ricorsivo devo chiamare self.license_file.save con l'arg save = False. – Greg

+0

@Greg grazie, il problema ricorsivo è davvero fastidioso. – laike9m

18

accettata è certamente una buona soluzione, ma qui è il modo in cui sono andato sulla generazione di un file CSV e servire da un punto di vista.

#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 

pensato che valeva la pena di mettere questo qui come mi c'è voluto un po 'di giocherellare per ottenere tutti i comportamenti desiderabili (sovrascrivere file esistente, la memorizzazione al punto giusto, senza la creazione di file duplicati, ecc).

Django 1.4.1

Python 2.7.3

0

Grazie @tawmas. Inoltre,

Ho ricevuto un errore se non si specifica la modalità file durante l'apertura del file. Così,

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

Per tipo ZIP di file

f = open('/path/to/file.zip', 'rb') 
Problemi correlati