2011-10-25 31 views
15

Aquí está el problema, tengo un formulario que contiene un campo de Django del archivo, a saber:Formulario Django archivo de campo desaparece en forma de error

photo = forms.FileField(help_text="Please attach a photo", required=False) 

Si la forma valida, el campo Archivo está delimitada y guardado correctamente. El problema es cuando el usuario rellena todo el formulario y no lo valida: la ruta del archivo seleccionado desaparece.

Por lo tanto, si el usuario no se da cuenta de esto, él/ella arregla los otros campos de errores y envía nuevamente - sin foto esta vez.

Por si acaso, se crea el formulario en la vista de la siguiente manera:

ProfileForm(request.POST or None, request.FILES or None) 

y el código HTML es:

<div id="uniform-id_photo" class="uploader"> 
    <input id="id_photo" class="clearablefileinput" type="file" name="photo" size="19" style="opacity: 0;"> 
    <span class="filename" style="-moz-user-select: none;">No file selected</span> 
    <span class="action" style="-moz-user-select: none;">Choose File</span> 
</div> 

Alguien ha tenido el mismo problema antes? ¿Alguna idea de una solución? :)

Gracias!

+0

Si miras el administrador de django, cada vez que envíes un formulario incorrecto, restablecerá las rutas de los archivos. Supongo que no hay forma de hacerlo, pero ¿por qué no resaltar el campo de archivo en su html? – iva123

+0

Sí, esa sería probablemente la mejor manera fácil de llamar la atención del usuario. ¡Gracias! – Sam

Respuesta

26

Desafortunadamente, este es un problema (realmente una característica de seguridad) impuesto por los navegadores, y no se puede resolver, como tal. Los navegadores no le permitirán especificar un valor inicial para las entradas de archivos, y no hay nada que pueda hacer para evitarlo.

La razón es que si un sitio web pudiera hacer esto, se abriría un vector que permitiría a cualquier sitio web robar cualquier archivo en su computadora al adivinar las rutas de archivos; podría tener un script ejecutándose en segundo plano que intentado publicar archivos interesantes en el servidor.

La única solución consiste en guardar realmente el archivo cargado en el servidor, independientemente de si el formulario se valida, y luego cuando devuelve el formulario y los errores al usuario, indica que ha recibido un archivo y que solo deberían complete ese campo para reemplazarlo.

+0

Veo, tiene sentido. Gracias por la respuesta amable y detallada! – Sam

+0

Otra solución es realizar una solicitud AJAX para validar el formulario. –

0

escribo alguna solución:

class CustomClearableFileInput(ClearableFileInput): 

def render(self, name, value, attrs=None): 
    if len(<YourModel>.objects.filter(id=self.form_instance_id))>0: 
     file = <YourModel>.objects.get(id=self.form_instance_id).<yourField> 
    else: 
     file = '' 
    substitutions = { 
     'initial_text': self.initial_text, 
     'input_text': self.input_text, 
     'clear_template': '', 
     'clear_checkbox_label': self.clear_checkbox_label, 
    } 
    template = '%(input)s' 
    substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs) 
    self.template_with_initial = ('<p class="file-upload">%s</p>' 
         % self.template_with_initial) 
    self.template_with_clear = ('<span class="clearable-file-input">%s</span>' 
         % self.template_with_clear) 

    if value and hasattr(value, "url"): 
     template = self.template_with_initial 
     substitutions['initial'] = format_html(self.url_markup_template, 
               value.url, 
               force_text(value)) 
     if not self.is_required: 
      checkbox_name = self.clear_checkbox_name(name) 
      checkbox_id = self.clear_checkbox_id(checkbox_name) 
      substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name) 
      substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id) 
      substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id}) 
      substitutions['clear_template'] = self.template_with_clear % substitutions 
      url = '' if file == '' else file.url 
    else: 
     template = self.template_with_initial 

     substitutions['initial'] = format_html(self.url_markup_template, 
               url, 
               force_text(file)) 
     if not self.is_required: 
      checkbox_name = self.clear_checkbox_name(name) 
      checkbox_id = self.clear_checkbox_id(checkbox_name) 
      substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name) 
      substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id) 
      if fav == '': 
       substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id, 'disabled': 'disabled'}) 
      else: 
       substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id}) 
      substitutions['clear_template'] = self.template_with_clear % substitutions 



    return mark_safe(template % substitutions) 

Y luego en su forma se debe escribir:

class <YourModel>Form(ModelForm): 
    class Meta: 
     model = <YourModel> 
     fields = '__all__' 
     widgets= {'<YourField>': CustomClearableFileInput} 

    def __init__(self, *args, **kwargs): 
     super(OperatorSettingsForm, self).__init__(*args, **kwargs) 
     self.fields['<YourField>'].widget.form_instance_id = self.instance.id 

Funciona para mí. Creo que tampoco tendrás ningún problema :)

Cuestiones relacionadas