Django - comment créer un fichier et le sauvegarder dans le champ de fichier d'un modèle?

Voici mon modèle. Ce que je veux faire, c'est générer un nouveau fichier et écraser le fichier existant chaque fois qu'une instance modèle est sauvegardée:

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)

je vois beaucoup de documentation sur la façon de télécharger un fichier. Mais comment puis-je générer un fichier, l'affecter à un champ Modèle et faire en sorte que Django le stocke au bon endroit?

71
demandé sur Greg 2011-09-22 16:49:24

3 réponses

vous voulez avoir un oeil à FileField et FieldFile dans le Django docs, et surtout FieldFile.save () .

fondamentalement , un champ déclaré comme un FileField , lorsqu'il est accédé , vous donne une instance de classe FieldFile , ce qui vous donne plusieurs méthodes pour interagir avec le fichier sous-jacent. Donc, ce que vous devez faire est:

self.license_file.save(new_name, new_contents)

new_name est le nom de fichier que vous souhaitez attribué et new_contents est le contenu du fichier. Notez que new_contents doit être une instance de django.core.files.File ou django.core.files.base.ContentFile (voir les liens donnés au manuel pour les détails). Deux choix se résument à:

# 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'))
105
répondu tawmas 2018-04-03 12:20:53

Accepté réponse est certainement une bonne solution, mais ici, c'est la façon dont je suis allé sur la génération d'un fichier CSV et de le servir à partir d'un point de vue.

#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

a pensé qu'il valait la peine de mettre ceci ici car il m'a fallu un peu de bricolage pour obtenir tous les comportements souhaitables (écraser fichier existant, stocker au bon endroit, ne pas créer des fichiers dupliqués etc).

Django 1.4.1

Python 2.7.3

19
répondu markdsievers 2013-02-14 23:52:02

Merci @tawmas. En outre,

j'ai une erreur si Je ne spécifie pas le mode fichier lors de l'ouverture du fichier. So,

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

Pour fichier ZIP,

f = open('/path/to/file.zip', 'rb')
0
répondu rajagopalx 2017-12-14 19:43:13