如何在Django中将本地文件分配给FileField?

46

我试图将硬盘上的文件分配给FileField,但是我遇到了这个错误:

AttributeError: 'str'对象没有属性'open'

我的Python代码:

pdfImage = FileSaver()
pdfImage.myfile.save('new', open('mytest.pdf').read())

我的models.py文件

class FileSaver(models.Model):

    myfile = models.FileField(upload_to="files/")

    class Meta:
        managed=False

非常感谢您提前的帮助。

4个回答

58
Django使用自己的文件类型(功能略有增强)。无论如何,Django的文件类型类似于装饰器,因此您可以简单地将其包装在现有文件对象周围,以满足Django API的需求。
from django.core.files import File

local_file = open('mytest.pdf')
djangofile = File(local_file)
pdfImage.myfile.save('new', djangofile)
local_file.close()

当然,您可以通过编写以下内容(少一行)来即时装饰文件:

pdfImage.myfile.save('new', File(local_file))

4
覆盖 <type 'file'> 可能是一个不好的主意。最好使用 file_ 。 - Aaron McMillin
8
仅为解释上面的评论(我有点困惑),亚伦谈论的是符号“file”(即变量名称),而不是传递的参数类型。 - Joe
记得关闭Python文件对象和Django文件对象。 - Rune Kaagaard
1
如果你收到了UnicodeDecodeError错误,试着以二进制模式打开文件:local_file = open("mytest.pdf", "rb") - nik_m
1
由于答案中的“file”变量已被重命名为“local_file”,因此@AaronMcMillin的评论不再有意义。 - Alan Evangelista

4

如果您不想打开文件,也可以将文件移动到媒体文件夹,并直接使用相对于MEDIA_ROOT的路径设置myfile.name:

import os
os.rename('mytest.pdf', '/media/files/mytest.pdf')
pdfImage = FileSaver()
pdfImage.myfile.name = '/files/mytest.pdf'
pdfImage.save()

3
如果您想在Django中上传本地文件,可以按照以下步骤操作:
from django.core.files import File

file = open(filepath, 'rb')
file_to_upload = File(file, name=f'{your_desired_name}')
file.close()

现在,您可以将文件传递给Django Rest Serializer进行上传或任何其他用途。如果将此文件传递给序列化器,请确保在将其传递给序列化器后关闭它。
注意:此处的文件路径可以是Django的临时文件或任何存储的文件。

2

如果您遇到以下错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position...

接下来你需要以二进制模式打开文件:open("mytest.pdf", "rb")

完整示例:

from django.core.files import File

pdfImage = FileSaver()
pdfImage.myfile.save('new.pdf', File(open('mytest.pdf','rb')))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接