Метод open () Django FileField (или ImageField) возвращает None для действительного файла? - PullRequest
23 голосов
/ 24 февраля 2012

позвольте мне сказать это так:

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)

Ответы [ 4 ]

29 голосов
/ 24 февраля 2012

потому что метод open моделей. FileField ничего не возвращает

, вы можете просто использовать:

task.seq_file.read()

и вам не нужно вычислять путь к файлу для проверки, существует ли файл,Вы можете использовать task.seq_file.path:

if not os.path.isfile(task.seq_file.path):
    ....
7 голосов
/ 24 февраля 2012

A FileField даст вам файлоподобный объект, и нет необходимости вызывать open () для него. В вашем примере просто позвоните task.seq_file.file.

Почему это? Для FileField существует много серверных хранилищ, и многие из них не поддерживаются файлом на диске (например, хранилище S3). Я предполагаю, что именно поэтому в документации сказано, что он возвращает объект, похожий на файл, а не файл. Для некоторых видов хранения «открытый» метод не имеет смысла.

3 голосов
/ 18 декабря 2013

В случае сомнений проверьте код.Вот выдержка из 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 голосов
/ 23 декабря 2016

Удивительно, но 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...