2012-02-23 13 views
18

déjame ponerlo de esta manera:El método Django FileField (o ImageField) open() devuelve Ninguno para el archivo válido?

model.py:

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

ajax.py (estoy usando dajaxice pero no importa):

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

Esto devuelve :

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' 

pero:

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

funciona a la perfección! ¿Por qué?

(estoy usando Django 1.3)

Respuesta

25

porque método abierto de models.FileField no devuelve nada

sólo puede utilizar:

task.seq_file.read() 

y que no es necesario calcular la ruta del archivo para comprobar si el archivo existe. puede usar task.seq_file.path:

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

Entonces, ¿cuál es el propósito de FileField open()? – mnowotka

+17

Lamentablemente, la documentación de Django es actualmente engañosa en este punto: "Se comporta como el método estándar Python open() ..." - https: //docs.djangoproject.com/en/1.4/ref/models/fields/# filefield-and-fieldfile No, devolver None después de realizar una misteriosa operación de apertura interna no es el comportamiento estándar de Python. –

+1

debería plantear un problema al respecto. – laike9m

7

Un FileField le dará un objeto de fichero y no hay necesidad de llamar a open() en él. En su ejemplo, simplemente llame al task.seq_file.file.

¿Por qué es eso? Hay muchos backends de almacenamiento para FileField, y muchos de ellos no están respaldados por un archivo en el disco (piense en el almacenamiento S3, por ejemplo). Supongo que es por eso que la documentación dice que devuelve un objeto similar a un archivo, no un archivo. Para algunos tipos de almacenamiento, el método "abierto" no tiene sentido.

+1

Pero de acuerdo con django FileField documentación es un proxy de archivos y puedo llamar abierto sobre ese objeto. Ni siquiera recibí el error sobre el método no definido por lo que está allí, ¿verdad? Entonces, ¿es un error o simplemente no entiendo algo? – mnowotka

+2

@mnowotka: está allí, pero nunca lo he usado, FileField le dará un objeto similar a un archivo (ya "abierto"). –

+0

tenga en cuenta que FileField no está necesariamente respaldado por un archivo en disco (S3, otros tipos de almacenamiento en la nube) –

3

En caso de duda, verifique el código. He aquí un extracto de 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 

Así, en el caso de un FileField, open vuelve a abrir el archivo con el modo especificado. Luego, una vez que llame al open, puede continuar usando métodos como read usando el nuevo modo aplicado.

0

Sorprendentemente, pero django.db.models.fields.files no utiliza file.storage.exists() método así que tuve que poner en práctica mi propia función pequeño para tener registro de entrada compatible con el almacenamiento cruz de archivo real existencia física:

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