Django - как создать файл и сохранить его в FileField модели? - PullRequest
87 голосов
/ 22 сентября 2011

Вот моя модель. Я хочу создать новый файл и перезаписать существующий при каждом сохранении экземпляра модели:

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 хранить его в нужном месте?

Ответы [ 3 ]

131 голосов
/ 22 сентября 2011

Вы хотите взглянуть на FileField и FieldFile в документах Django, и особенно FieldFile.save () .

По сути, поле, объявленное какFileField при обращении дает вам экземпляр класса FieldFile, который дает вам несколько методов для взаимодействия с базовым файлом.Итак, что вам нужно сделать:

self.license_file.save(new_name, new_contents)

, где new_name - это имя файла, которое вы хотите назначить, а new_contents - это содержимое файла.Обратите внимание, что new_contents должен быть экземпляром либо django.core.files.File, либо django.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'))
21 голосов
/ 15 февраля 2013

Принятый ответ, безусловно, является хорошим решением, но я пошел по пути создания 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 голосов
/ 14 декабря 2017

Спасибо @tawmas.В дополнение к этому,

Я получил ошибку, если при открытии файла я не указал режим файла.Итак,

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

Для ZIP-файлов,

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