2012-02-23 16 views
18

讓我把這樣的:對於有效的文件,Django FileField(或ImageField)的open()方法返回None?

model.py:

class Task(models.Model): 
    ... 
    seq_file = models.FileField(upload_to='files/', blank=True, null=True) 
    ... 

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()) 
    ... 

這個回報:

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' 

但:

... 
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()) 
    ... 

完美地工作! 爲什麼?

(我使用Django 1.3)

回答

25

因爲models.FileField的open方法不返回任何

你可以使用:

task.seq_file.read() 

,你不需要計算文件的路徑,如果文件存在檢查。您可以使用task.seq_file.path:

if not os.path.isfile(task.seq_file.path): 
    .... 
+12

那麼FileField open()的目的是什麼? – mnowotka 2012-02-23 22:17:24

+17

不幸的是,Django文檔在這一點上目前是誤導性的:「像標準Python open()方法一樣......」 - https://docs.djangoproject。com/en/1.4/ref/models/fields /#filefield-and-fieldfile 不,在執行神祕的內部打開操作後返回None不是標準的Python行爲。 – 2012-09-20 03:20:32

+1

應該對此提出問題。 – laike9m 2013-09-29 00:27:54

7

一個FileField會給你一個類似文件的對象,也沒有必要調用open()就可以了。在你的例子中,只需撥打task.seq_file.file即可。

這是爲什麼? FileField有很多存儲後端,並且其中很多都不支持磁盤中的文件(例如,考慮S3存儲)。我想這就是爲什麼文檔說它返回一個類文件對象,而不是文件。對於某些類型的存儲,「開放」方法是沒有意義的。

+1

但根據Django文檔的FileField是一個文件代理我可以打電話給那個對象。我甚至沒有得到關於未定義方法的錯誤,所以它就在那裏,對吧?所以這是一個錯誤,或者我只是不明白什麼? – mnowotka 2012-02-23 22:04:39

+2

@mnowotka:它在那裏,但我從來沒有使用它,FileField會給你一個類似文件的對象(已經「打開」)。 – 2012-02-23 22:21:46

+0

請記住,FileField不一定支持磁盤上的文件(S3,其他類型的雲存儲) – 2015-09-25 22:35:50

3

如有疑問,請檢查代碼。下面是django.db.models.fields.files的摘錄:

def open(self, mode='rb'): 
    self._require_file() 
    self.file.open(mode) 
# open() doesn't alter the file's contents, but it does reset the pointer 
open.alters_data = True 

所以,在FileField的情況下,重新打開open使用指定的模式文件。然後,一旦您撥打open,您可以繼續使用像read這樣的方法使用新應用的模式。

0

令人驚訝,但django.db.models.fields.files不使用file.storage.exists()方法,所以我不得不來實現我自己的小功能,有實際的物理文件存在的交叉存儲兼容檢查:

# Check whether actual file of FileField exists (is not deleted/moved out). 
def file_exists(obj): 
    return obj.storage.exists(obj.name) 
相關問題