Django FileField(或ImageField)open()方法为有效文件返回None?

mno*_*tka 24 python django

让我这样说:

model.py:

class Task(models.Model):
    ...
    seq_file = models.FileField(upload_to='files/', blank=True, null=True)
    ...
Run Code Online (Sandbox Code Playgroud)

ajax.py(我使用的是dajaxice,但没关系):

...
def startTask(request, name):
    task = Task.objects.get(task_name=name)
    data = task.seq_file.open()
    filename = os.path.join(settings.MEDIA_ROOT ,task.seq_file.name)
    if not os.path.isfile(filename):
        raise Exception, "file " + filename + " not found."
    sequences = parser.parse(data.read())
    ...
Run Code Online (Sandbox Code Playgroud)

这会返回:

File "/home/mnowotka/Dokumenty/MgrFuncAdnot/app/django-gui/src/gui/ajax.py", line 43, in startTask
sequences = parser.parse(data.read())

AttributeError: 'NoneType' object has no attribute 'read'
Run Code Online (Sandbox Code Playgroud)

但:

...
def startTask(request, name):
    task = Task.objects.get(task_name=name)
    filename = os.path.join(settings.MEDIA_ROOT ,task.seq_file.name)
    if not os.path.isfile(filename):
        raise Exception, "file " + filename + " not found."
    data = open(filename)  
    sequences = parser.parse(data.read())
    ...
Run Code Online (Sandbox Code Playgroud)

完美运作!为什么?

(我正在使用django 1.3)

小智 29

因为模型的open方法.FileField不返回任何内容

你可以使用:

task.seq_file.read()
Run Code Online (Sandbox Code Playgroud)

并且您不需要计算文件路径来检查文件是否存在.你可以使用task.seq_file.path:

if not os.path.isfile(task.seq_file.path):
    ....
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,Django文档目前在这一点上有误导性:"表现得像标准的Python open()方法......" - https://docs.djangoproject.com/en/1.4/ref/models/fields/#filefield-and -fieldfile不,执行神秘的内部打开操作后返回None不是标准的Python行为. (21认同)
  • 那么FileField open()的目的是什么? (13认同)
  • 我最近偶然发现了这个问题,只是在这里提交了一张票和对文档的潜在改进:https://code.djangoproject.com/ticket/26508 (4认同)

Pau*_*ine 8

A FileField会给你一个类文件对象,不需要调用open()就可以了.在你的例子中,只需要打电话task.seq_file.file.

这是为什么?有许多存储后端FileField,其中许多不受磁盘中文件的支持(例如,考虑S3存储).我猜这就是文档说它返回类似文件的对象而不是文件的原因.对于某些类型的存储,"开放"方法毫无意义.

  • @mnowotka:它就在那里,但我从未使用它,FileField会给你一个类似文件的对象(已经"打开"). (2认同)