2011-10-25 17 views
15

Qui è il problema, ho un modulo Django contenente un campo di file, vale a dire:Campo Django Modulo File scompare errore di forma

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

Se il modulo convalida, il campo File è delimitata e salvato correttamente. Il problema è quando l'utente riempie tutto il modulo e non convalida: il percorso del file selezionato scompare.

Quindi, se l'utente non si rende conto di questo, lui/lei correggo gli altri campi errori e invii di nuovo - senza foto questa volta.

Solo nel caso, la forma viene creata nella vista in questo modo:

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

e l'HTML è:

<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> 

Qualcuno ha avuto lo stesso problema prima? Qualche idea per una soluzione? :)

Grazie!

+0

Se guardi l'admin di django, ogni volta che invii un modulo non corretto reimposta i percorsi dei file. Immagino che non ci sia modo di farlo ma perché non evidenziare il campo file nel tuo html? – iva123

+0

Sì, sarebbe probabilmente il modo migliore per richiamare l'attenzione dell'utente. Grazie! – Sam

risposta

26

Sfortunatamente, questo è un problema (davvero una caratteristica di sicurezza) imposto dai browser, e non è risolvibile, in quanto tale. I browser non ti consentono di specificare un valore iniziale per gli input dei file e non c'è nulla che tu possa fare per ovviare a questo problema.

Il motivo è che se un sito Web potrebbe eseguire questa operazione, si aprirà un vettore che consentirebbe a qualsiasi sito Web di rubare qualsiasi file sul computer indovinando i percorsi dei file - potrebbero semplicemente avere uno script in esecuzione in background che ho provato a pubblicare file interessanti sul server.

L'unica soluzione è di salvare effettivamente il file caricato sul server indipendentemente dal fatto che il modulo venga convalidato, e quindi quando si restituisce il modulo e gli errori all'utente, indicare che si è ricevuto un file e che devono solo compilare quel campo per sostituirlo.

+0

Vedo, ha senso. Grazie per la risposta gentile e dettagliata! – Sam

+0

Un'altra soluzione è eseguire una richiesta AJAX per convalidare il modulo. –

0

scrivo qualche soluzione:

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) 

E poi nel modulo è necessario scrivere:

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 

Funziona per me. Penso che anche tu non avrai problemi :)

Problemi correlati