2011-02-17 17 views
9

¿Alguien me puede indicar exactamente cuándo se ha escrito un archivo cargado en la ubicación devuelta por "upload_to" en FileField, en particular con respecto al orden del campo, modelo, y validación y limpieza de formularios?Validación de formulario Django, clean() y carga de archivos

Ahora tengo un método "limpio" en mi modelo que asume que el archivo cargado está en su lugar, por lo que puede validarlo. Parece que el archivo aún no se ha guardado y puede que solo se guarde en una ubicación temporal o en la memoria. Si ese es el caso, ¿cómo lo "abro" o busco una ruta si necesito ejecutar algún proceso/programa externo para validar el archivo?

Gracias,

Ian

Respuesta

8

La forma de limpieza no tiene nada que ver con el hecho de guardar el archivo, o con el ahorro de cualquier otro dato para el caso. El archivo no se guarda hasta que ejecute el método save() de la instancia del modelo (tenga en cuenta que si usa ModelName.objects.create() este método save() se llama automáticamente).

El formulario enlazado contendrá un objeto de archivo abierto, por lo que debería poder realizar cualquier validación sobre ese objeto directamente. Por ejemplo:

form = MyForm(request.POST, request.FILES) 
if form.is_valid(): 
    file_object = form.cleaned_data['myFile'] 
    #run any validation on the file_object, or define a clean_myFile() method 
    # that will be run automatically when you call form.is_valid() 

    model_inst = MyModel('my_file' = file_object, 
        #assign other attributes here.... 
        ) 
    model_inst.save() #file is saved to disk here 
+0

Cualquier forma de hacerlo en la validación del modelo en lugar de en la validación de formularios? – IanSR

+0

¿dónde debería colocarse este código? – andi

3

¿Qué necesitas hacer en él? Si su validación funcionará sin un archivo temporal, puede acceder a los datos llamando al read() sobre lo que devuelve su campo de archivo.

def clean_field(self): 
    _file = self.cleaned_data.get('filefield') 
    contents = _file.read() 

Si lo hace lo necesitan en el disco, que sabemos a dónde ir desde aquí :) escribirlo en una ubicación temporal y hacer algo de magia en él!

+0

Me gustaría que esta validación vaya al método ** Model.clean() **, en lugar de la validación del formulario, pero parece que esto no es posible, ¿es correcto? La validación de archivos cargados solo puede ocurrir en el nivel Formulario, por lo que parece que estás diciendo. – IanSR

+0

Espera, no importa, recuerdo haber leído una publicación de SO sobre cómo hacerlo ... déjame ir a cavar. Lo siento no puedo encontrarlo. Si el modelo ya está guardado, puede acceder a 'self.field.file.read()' –

0

O escríbalo como un campo de formulario personalizado. Esta es la idea básica de cómo hago para verificar un archivo MP3 usando la biblioteca 'mutagen'.

Notas:

  • primera comprobar el tamaño del archivo a continuación, si es correcto el tamaño de escritura a TMP ubicación.
  • Escribirá el archivo en la ubicación temporal especificada en AJUSTES, revise su MP3 y luego bórrelo.

El código:

from django import forms 

import os 
from mutagen.mp3 import MP3, HeaderNotFoundError, InvalidMPEGHeader 

from django.conf import settings 

class MP3FileField(forms.FileField): 

    def clean(self, *args, **kwargs): 
     super(MP3FileField, self).clean(*args, **kwargs) 
     tmp_file = args[0] 

     if tmp_file.size > 6600000: 
      raise forms.ValidationError("File is too large.") 

     file_path = getattr(settings,'FILE_UPLOAD_TEMP_DIR')+'/'+tmp_file.name 

     destination = open(file_path, 'wb+') 
     for chunk in tmp_file.chunks(): 
      destination.write(chunk) 
     destination.close() 

     try: 
      audio = MP3(file_path) 
      if audio.info.length > 300: 
       os.remove(file_path) 
       raise forms.ValidationError("MP3 is too long.") 

     except (HeaderNotFoundError, InvalidMPEGHeader): 
      os.remove(file_path) 
      raise forms.ValidationError("File is not valid MP3 CBR/VBR format.") 
     os.remove(file_path) 
     return args 
Cuestiones relacionadas